ERR_HTTP2_INVALID_STREAM
Node.jsERRORNotableHTTP/2HIGH confidence

Operation attempted on a destroyed or closed HTTP/2 stream

Production Risk

Unhandled, causes uncaught exceptions that crash the server process.

What this means

Thrown when an HTTP/2 stream operation is attempted after the stream has been destroyed or closed. Once a stream is closed via RST_STREAM or normal completion, no further reads, writes, or header operations are valid.

Why it happens
  1. 1Writing to a stream after the remote side sent RST_STREAM
  2. 2Async handler resuming after the stream has timed out and closed
  3. 3Calling stream.respond() after stream.destroy()
How to reproduce

Triggered when any I/O or header operation is attempted on a stream with destroyed === true.

trigger — this will error
trigger — this will error
server.on('stream', async (stream) => {
  stream.destroy();
  stream.respond({ ':status': 200 }); // throws
});

expected output

Error [ERR_HTTP2_INVALID_STREAM]: The stream has been destroyed

Fix

Check stream.destroyed before operating on it

WHEN In async handlers where the stream may have closed

Check stream.destroyed before operating on it
server.on('stream', async (stream) => {
  const data = await fetchData();
  if (stream.destroyed) return;
  stream.respond({ ':status': 200 });
  stream.end(JSON.stringify(data));
});

Why this works

Checking stream.destroyed prevents operations on streams that have already been torn down.

Code examples
Triggerjs
server.on('stream', async (stream) => {
  stream.destroy();
  stream.respond({ ':status': 200 }); // throws
});  // this triggers ERR_HTTP2_INVALID_STREAM
Handle in try/catchjs
try {
  // operation that may throw ERR_HTTP2_INVALID_STREAM
  riskyOperation()
} catch (err) {
  if (err.code === 'ERR_HTTP2_INVALID_STREAM') {
    console.error('ERR_HTTP2_INVALID_STREAM:', err.message)
  } else {
    throw err
  }
}
Defensive pattern to avoid itjs
// Validate inputs before calling the operation
function safe_err_http2_invalid_stream(...args) {
  // validate args here
  return performOperation(...args)
}
What not to do

Ignore stream lifecycle in async handlers

Awaited operations give time for the stream to close; always check destroyed before responding.

Same error in other languages
Sources
Official documentation ↗

Node.js Error Codes Documentation

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All Node.js errors