{"record":{"id":"b37d019c84c0fb01","repo":"decolua/9router","slug":"passthrough-error-e-message","errorCode":null,"errorMessage":"Passthrough error: ${e.message}","messagePattern":"Passthrough error: (.+?)","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"src/mitm/server.js","lineNumber":283,"sourceCode":"      forwardRes.pipe(res);\n      return;\n    }\n\n    const chunks = [];\n    forwardRes.on(\"data\", chunk => {\n      if (dumper) dumper.writeChunk(chunk);\n      if (onResponse) chunks.push(chunk);\n      res.write(chunk);\n    });\n    forwardRes.on(\"end\", () => {\n      if (dumper) dumper.end();\n      res.end();\n      if (onResponse) try { onResponse(Buffer.concat(chunks), forwardRes.headers); } catch { /* ignore */ }\n    });\n  });\n\n  forwardReq.on(\"error\", (e) => {\n    err(`Passthrough error: ${e.message}`);\n    if (dumper) { dumper.writeChunk(`\\n[ERROR] ${e.message}\\n`); dumper.end(); }\n    if (!res.headersSent) res.writeHead(502);\n    res.end(\"Bad Gateway\");\n  });\n\n  if (bodyBuffer.length > 0) forwardReq.write(bodyBuffer);\n  forwardReq.end();\n}\n\n// ── Request handler ───────────────────────────────────────────\n\nconst server = https.createServer(sslOptions, async (req, res) => {\n  try {\n    if (req.url === \"/_mitm_health\") {\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify({ ok: true, pid: process.pid }));\n      return;\n    }","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/mitm/server.js#L265-L301","documentation":"In passthroughHttps, the http.request forwarded to the real upstream emits an 'error' on the request object. The handler logs 'Passthrough error: <message>', writes it to the dump, replies 502 Bad Gateway ('Bad Gateway' body) if headers were not sent.","triggerScenarios":"The HTTPS forwarding request fails before a response — DNS ENOTFOUND on the target host, ECONNREFUSED/ETIMEDOUT connecting to port 443, TLS handshake failure, or socket destroyed early.","commonSituations":"Hosts-file/DNS override pointing the domain at a dead IP; no network/VPN; upstream provider outage; SNI/TLS interception interference from corporate proxies.","solutions":["Check the underlying code (ENOTFOUND/ECONNREFUSED/ETIMEDOUT) to distinguish DNS vs connectivity vs timeout.","Fix DNS/hosts entries if the domain resolves to a stale MITM IP.","Verify outbound internet/VPN connectivity with curl to the target domain.","Retry on timeout — transient upstream outages surface here."],"exampleFix":"// before\ngetaddrinfo ENOTFOUND api.example.com → 502 Bad Gateway\n// after\n# fix hosts/DNS, then verify\nnslookup api.example.com && curl -I https://api.example.com","handlingStrategy":"retry","validationCode":"try {\n  const addr = await dns.promises.lookup(targetHost);\n  console.log(`[mitm] ${targetHost} -> ${addr.address}`);\n} catch (e) {\n  return respond502(`DNS failure: ${e.code}`); // ENOTFOUND caught before forwarding\n}","typeGuard":"function isDnsError(e) { return e && (e.code === 'ENOTFOUND' || e.code === 'EAI_AGAIN'); }\nfunction isConnRefused(e) { return e && e.code === 'ECONNREFUSED'; }","tryCatchPattern":"forwardReq.on('error', (e) => {\n  err(`Passthrough error: ${e.message}`);\n  if (isDnsError(e) || isConnRefused(e)) {\n    if (!res.headersSent) res.writeHead(502, { 'Content-Type': 'application/json' });\n    return res.end(JSON.stringify({ error: { message: e.message, hint: 'check DNS/upstream' } }));\n  }\n  if (!res.headersSent) res.writeHead(502);\n  res.end('Bad Gateway');\n});","preventionTips":["Verify hosts/DNS overrides resolve to the intended IP before enabling MITM.","Check network/VPN connectivity when many passthrough requests fail at once.","Add one retry for transient ETIMEDOUT/ECONNRESET on idempotent requests.","Clean up MITM DNS entries on shutdown to avoid stale overrides."],"tags":["https","mitm","dns","bad-gateway"],"backgroundTag":"connection-refused","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}