ChromeDevTools / ChromeDevTools/chrome-devtools-mcp
ConsoleCollector passes no per-navigation cap to PageCollector, so console messages on one navigation are retained without limit
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 52.3k
- Forks
- 4.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 83
Description
Description of the bug
PageCollector accepts an optional maxResourcesPerNavigation and trims the current navigation's bucket when one is supplied. NetworkCollector passes MAX_REQUESTS_PER_NAVIGATION = 1_000, and ServiceWorkerConsoleCollector keeps its own maxLogs = 1000. ConsoleCollector calls super(page, listeners) with two arguments, so the cap is undefined, the trim branch never runs, and every console message on a navigation is retained for as long as that navigation lasts.
maxNavigationSaved = 3 bounds the number of buckets, not the number of messages in one. A page that does not navigate has exactly one bucket, and it grows without limit. Since #2676 (fix for #2650), same-document navigations deliberately no longer rotate the history. That is the right behaviour for list_console_messages, but it means a single-page app's entire session now lands in that one uncapped bucket.
Cited at main = 882f93e:
- The cap is optional: https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/882f93e9a8809fe88eced35d793951fb456b7117/src/collectors/PageCollector.ts#L65
- The trim only runs when it was supplied: https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/882f93e9a8809fe88eced35d793951fb456b7117/src/collectors/PageCollector.ts#L76-L84
ConsoleCollectorsupplies none: https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/882f93e9a8809fe88eced35d793951fb456b7117/src/collectors/PageCollector.ts#L196-L211NetworkCollectordoes: https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/882f93e9a8809fe88eced35d793951fb456b7117/src/collectors/PageCollector.ts#L375-L392ServiceWorkerConsoleCollector, the same kind of data for another target, bounds itself: https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/882f93e9a8809fe88eced35d793951fb456b7117/src/collectors/ServiceWorkerCollector.ts#L79-L81 and https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/882f93e9a8809fe88eced35d793951fb456b7117/src/collectors/ServiceWorkerCollector.ts#L169-L170
The same two-argument call is present in the released 1.9.0 (build/src/collectors/PageCollector.js, super(page, listeners);).
Prior art. #1221 proposed exactly this cap (1000 for ConsoleCollector) in March. It was attached to #1214, which was closed as a duplicate of the --autoConnect leak (#1192), and the PR has not been reviewed. It also targets the pre-move path src/PageCollector.ts. Filing this separately so the console bound is decided on its own merits rather than riding on a closed, unrelated issue.
Reproduction
Run against the installed 1.9.0 package. The shipped ConsoleCollector class is imported unmodified; only the Puppeteer Page and its CDP session are stubbed.
// PKG=<path to an installed chrome-devtools-mcp> node repro.mjs
const {ConsoleCollector} = await import(`${process.env.PKG}/build/src/collectors/PageCollector.js`);
const noop = () => {};
const emitter = () => { const h = {}; return {h, on: (n, f) => { (h[n] ||= []).push(f); }, off: noop, once: noop, emit: (n, ...a) => (h[n]||[]).forEach(f => f(...a))}; };
const session = Object.assign(emitter(), {send: async () => ({}), target: () => ({_targetId: 't1'})});
const page = Object.assign(emitter(), {_client: () => session, mainFrame: () => emitter()});
const c = new ConsoleCollector(page, collect => ({console: collect}));
const N = 50_000;
for (let i = 0; i < N; i++) page.emit('console', {type: () => 'log', text: () => `m${i}`});
console.log(`ConsoleCollector: emitted ${N} console events on one navigation -> retained ${c.getData(false).length}`);
Observed:
ConsoleCollector: emitted 50000 console events on one navigation -> retained 50000
For contrast, the same input driven through PageCollector with and without NetworkCollector's cap:
NetworkCollector.MAX_REQUESTS_PER_NAVIGATION = 1000
pushed 50000 items:
with a cap (NetworkCollector's shape) -> retained 1000
no cap (ConsoleCollector's shape) -> retained 50000
Expectation
Console retention per navigation is bounded, as network requests and service-worker console logs already are.
A possible fix, mirroring NetworkCollector (a named constant plus a defaulted constructor parameter, so a caller can still opt out). No change to PageCollector is needed, because the trim it already implements simply starts running:
export class ConsoleCollector extends PageCollector<…> {
static readonly MAX_MESSAGES_PER_NAVIGATION = 1_000;
constructor(
page: Page,
listeners: …,
maxMessagesPerNavigation = ConsoleCollector.MAX_MESSAGES_PER_NAVIGATION,
) {
super(page, listeners, maxMessagesPerNavigation);
Two things you are better placed to judge:
- Which end to keep.
splicefrom the front drops the oldest messages, which is what the siblings do. Console output is often most useful early in a page's life, where the first errors appear. If that matters here, a head-and-tail retention would serve better. Either bound is an improvement on none. - Default or required. Making
maxResourcesPerNavigationrequired onPageCollectorwould make this class of omission impossible rather than just fixing this instance. It is also a signature change, so it is mentioned rather than proposed.
Scope and honest limits. This is a structural report, not an incident: a buffer fed by page-controlled input with no bound, in a server designed to stay resident. On a long-lived shared deployment where pages stay open for hours, the live instance held 19 console messages when checked, so this has not caused a memory problem there. The concern is any page that logs in a loop or an SPA that is kept open, both of which are ordinary.
MCP configuration
Not relevant to the repro, which exercises the collector class directly. Observed in a long-lived server (one process shared by several MCP clients, headless, --experimentalPageIdRouting).
Chrome DevTools MCP version
1.9.0 (installed); the cited lines are re-read at main 882f93e.
Chrome version
Not involved (the page is stubbed).
Node version
v24.14.1
Operating system
Linux
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/collectors/PageCollector.ts at ConsoleCollector and compare its constructor with NetworkCollector and ServiceWorkerConsoleCollector. Run the supplied 50,000-event reproduction to confirm the uncapped retention, then verify that console messages per navigation are bounded while the existing navigation behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100