decolua/9router · error
[mitm] http2 stream error: ${e.message}
Error message
[mitm] http2 stream error: ${e.message} What it means
In passthroughHttp2, the HTTP/2 stream (opened with client.request after the session connects) errors out. The handler logs '[mitm] http2 stream error: <message>', records it in the dump, responds 502 if headers were not yet sent, ends the response, closes the client, and resolves.
Source
Thrown at src/mitm/server.js:239
res.writeHead(status, outHeaders);
if (dumper) dumper.writeHeader(status, outHeaders);
const chunks = [];
stream.on("data", chunk => {
if (dumper) dumper.writeChunk(chunk);
if (onResponse) chunks.push(chunk);
res.write(chunk);
});
stream.on("end", () => {
if (dumper) dumper.end();
if (!res.writableEnded) res.end();
if (onResponse) try { onResponse(Buffer.concat(chunks), outHeaders); } catch {}
try { client.close(); } catch {}
resolve();
});
});
stream.once("error", (e) => {
err(`[mitm] http2 stream error: ${e.message}`);
if (dumper) { dumper.writeChunk(`\n[ERROR h2-stream] ${e.message}\n`); dumper.end(); }
if (!res.headersSent) res.writeHead(502);
if (!res.writableEnded) res.end();
try { client.close(); } catch {}
resolve();
});
});
}
// Fallback: raw https.request HTTP/1.1 with custom DNS (bypasses /etc/hosts MITM loop)
async function passthroughHttps(req, res, bodyBuffer, headers, targetHost, onResponse, dumper) {
const targetIP = await resolveTargetIP(targetHost);
const forwardReq = https.request({
hostname: targetIP,
port: 443,
path: req.url,
method: req.method,
headers,View on GitHub (pinned to 90b52e06ff)
Solutions
- Read the h2 error name (e.g. PROTOCOL_ERROR vs CANCEL) — CANCEL is usually client-aborted and benign.
- Retry the request; REFUSED_STREAM under load is typically transient.
- If PROTOCOL_ERROR persists, force HTTP/1.1 for that host or update the MITM server code.
- Check upstream provider status for GOAWAY/reset storms.
Example fix
// before
stream.once('error', ...) → NGHTTP2_PROTOCOL_ERROR
// after: disable h2 for the problem host (fall back to passthroughHttps)
ALPNProtocols: ['http/1.1'] // in the tls.connect options Defensive patterns
Strategy: retry
Validate before calling
// distinguish client-abort (benign) from protocol errors before reacting
const benign = ['NGHTTP2_CANCEL', 'NGHTTP2_REFUSED_STREAM'];
if (!benign.includes(e.code)) console.warn(`h2 stream ${e.code} for ${targetHost}`); Type guard
function isStreamReset(e) {
return e && typeof e.code === 'string' && e.code.startsWith('NGHTTP2_');
}
function isClientAborted(e) {
return isStreamReset(e) && (e.code === 'NGHTTP2_CANCEL' || e.code === 'NGHTTP2_REFUSED_STREAM');
} Try / catch
stream.once('error', (e) => {
if (isClientAborted(e)) { try { client.close(); } catch {} ; return resolve(); } // benign
err(`[mitm] http2 stream error: ${e.message}`);
if (!res.headersSent) res.writeHead(502);
if (!res.writableEnded) res.end();
try { client.close(); } catch {}
resolve();
}); Prevention
- Treat CANCEL/REFUSED_STREAM as client-side aborts, not server faults.
- Fall back to HTTP/1.1 for hosts with persistent PROTOCOL_ERROR.
- Retry once on REFUSED_STREAM — it is often transient under load.
- Keep the h2 client settings (frame sizes, concurrency) within upstream defaults.
When it happens
Trigger: The h2 stream is reset (RST_STREAM/NGHTTP errors like PROTOCOL_ERROR, REFUSED_STREAM, CANCEL) after the client session connected — typically the upstream rejects or aborts the request, or the request stream is misused (headers/body sent after close).
Common situations: Upstream server sends GOAWAY or RST_STREAM under load; HTTP/2 protocol incompatibility with a specific provider; client aborted the request causing stream CANCEL propagation.
Related errors
- Cursor AgentService request failed: ${error.message}
- [mitm] http2 client error: ${e.message}
- Machine ID is required for Cursor API
- http2 module not available
- HTTP/2 is required for Cursor AgentService (endpoint is h2-o
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/0ae0b8ccacdb466f.
Report an issue: GitHub.