Operation attempted on a destroyed or closed HTTP/2 stream
Production Risk
Unhandled, causes uncaught exceptions that crash the server process.
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.
- 1Writing to a stream after the remote side sent RST_STREAM
- 2Async handler resuming after the stream has timed out and closed
- 3Calling stream.respond() after stream.destroy()
Triggered when any I/O or header operation is attempted on a stream with destroyed === true.
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
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.
server.on('stream', async (stream) => {
stream.destroy();
stream.respond({ ':status': 200 }); // throws
}); // this triggers ERR_HTTP2_INVALID_STREAMtry {
// 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
}
}// Validate inputs before calling the operation
function safe_err_http2_invalid_stream(...args) {
// validate args here
return performOperation(...args)
}✕ Ignore stream lifecycle in async handlers
Awaited operations give time for the stream to close; always check destroyed before responding.
Node.js Error Codes Documentation
Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev