Skip to content

inspector: Network.loadingFinished sent for a request the session never saw #66747

Open

Description

@harjothkhara

Version

v26.5.0 (also reproduces on v24.16.0 and on main)

Platform

Darwin arm64 (macOS)

Subsystem

inspector

What steps will reproduce the bug?

Run with node --experimental-network-inspection repro.js:

'use strict';
const http = require('http');
const inspector = require('inspector/promises');
const { once } = require('events');

(async () => {
  let held;
  const server = http.createServer((req, res) => { held = res; });
  server.listen(0, '127.0.0.1');
  await once(server, 'listening');

  // Session A sees the request start and the response headers.
  const a = new inspector.Session();
  a.connect();
  await a.post('Network.enable');
  const req = http.get(`http://127.0.0.1:${server.address().port}/`);
  while (!held) await new Promise((r) => setImmediate(r));
  held.writeHead(200);
  held.flushHeaders();
  const [res] = await once(req, 'response');
  a.disconnect();

  // Session B connects while the body is still pending.
  const b = new inspector.Session();
  b.connect();
  const events = [];
  for (const m of ['requestWillBeSent', 'responseReceived',
                   'loadingFinished', 'loadingFailed']) {
    b.on(`Network.${m}`, ({ params }) => events.push(`${m}:${params.requestId}`));
  }
  await b.post('Network.enable');
  res.resume();
  held.end('body');
  await once(res, 'end');
  await new Promise((r) => setImmediate(r));
  console.log(events);
  b.disconnect();
  server.close();
})();

How often does it reproduce? Is there a required condition?

Always. A session has to disconnect while a request is in flight, and another session has to enable the Network domain before that request completes.

What is the expected behavior? Why is that the expected behavior?

[]. Session B was never sent Network.requestWillBeSent for this request, so it should not get a terminal event for it. Network.responseReceived and Network.dataReceived are already dropped in this case, because the new session's agent has no entry for the request.

What do you see instead?

[ 'loadingFinished:node-network-event-1' ]

Additional information

NetworkAgent::loadingFinished and NetworkAgent::loadingFailed call the frontend unconditionally. The lookup in requests_ only runs afterwards, for bookkeeping. The same thing happens if the session disconnects before the response headers arrive.

Gating these two events on requests_ would not be correct: RequestsBuffer::enforceBufferLimits evicts entries for requests that are still in flight, so the session would never see those requests finish. A possible fix is a per-session set of announced request ids. requestWillBeSent would add to it, Network.enable/Network.disable would clear it, and loadingFinished/loadingFailed would remove the id and skip the frontend call if it wasn't there. I have a patch along these lines and can open a PR if that approach sounds right.

Activity

  1. inoway46 commented on Oct 15, 2026

    @inoway46
    Contributor

    I reproduced this on Node.js v26.12.0. Since Node.js uses CDP, I also checked Chrome, which emits loadingFinished in this scenario too. DevTools ignores the unknown request ID, and I observed no Network panel issues.
    This seems closer to expected behavior than a bug. Do you have a real-world use case where this causes a problem?

  2. added
    inspectorIssues and PRs related to the V8 inspector protocol.
    on Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    inspectorIssues and PRs related to the V8 inspector protocol.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions