{"record":{"id":"0a1a1875bbafa46f","repo":"slopus/happy","slug":"proxy-error","errorCode":null,"errorMessage":"Proxy error","messagePattern":"Proxy error","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"packages/happy-cli/src/modules/proxy/startHTTPDirectProxy.ts","lineNumber":25,"sourceCode":"    verbose?: boolean;\n    onRequest?: (req: IncomingMessage, proxyReq: ClientRequest) => void;\n    onResponse?: (req: IncomingMessage, proxyRes: IncomingMessage) => void;\n}\n\nexport async function startHTTPDirectProxy(options: HTTPProxyOptions) {\n    const proxy = httpProxy.createProxyServer({\n        target: options.target,\n        changeOrigin: true,\n        secure: false\n    });\n\n    let requestId = 0;\n\n    // Handle proxy errors\n    proxy.on('error', (err, req, res) => {\n        logger.debug(`[HTTPProxy] Proxy error: ${err.message} for ${req.method} ${req.url}`);\n        if (res instanceof ServerResponse && !res.headersSent) {\n            res.writeHead(500, { 'Content-Type': 'text/plain' });\n            res.end('Proxy error');\n        }\n    });\n\n    // Trace outgoing proxy requests\n    proxy.on('proxyReq', (proxyReq, req, res) => {\n        // const id = ++requestId;\n        // (req as any)._proxyRequestId = id;\n        \n        // logger.debug(`[HTTPProxy] [${id}] --> ${req.method} ${req.url}`);\n        // if (options.verbose) {\n        //     logger.debug(`[HTTPProxy] [${id}] --> Target: ${options.target}${req.url}`);\n        //     logger.debug(`[HTTPProxy] [${id}] --> Headers: ${JSON.stringify(req.headers)}`);\n        // }\n        \n        // Allow custom request handler\n        if (options.onRequest) {\n            options.onRequest(req, proxyReq);","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/modules/proxy/startHTTPDirectProxy.ts#L7-L43","documentation":"startHTTPDirectProxy wraps an http-proxy instance targeting `options.target`. When http-proxy emits its 'error' event — the upstream target is unreachable, DNS fails, the connection is refused/timed out, TLS verification fails, or the socket errors mid-request — the handler logs the cause and, if the client response hasn't already sent headers, replies HTTP 500 with the body 'Proxy error'.","triggerScenarios":"Any request forwarded through the proxy when the upstream `target` cannot be reached or errors: target server down, wrong target host/port, ECONNRESET from the upstream, target closing keep-alive sockets, or HTTPS certificate failures (proxy created with secure:false reduces but does not eliminate TLS errors).","commonSituations":"Local dev server not started (or crashed) while the proxy points at it; wrong `target` port in configuration; target restarted and in-flight keep-alive connections got reset; firewall/DNS blocking the target host; target killing long-running requests (streaming/SSE) mid-flight.","solutions":["Confirm the upstream `target` is running and reachable: `curl <target>` from the same machine; start/restart the target service if it's down.","Check the CLI file logs for '[HTTPProxy] Proxy error: ...' to see the underlying errno (ECONNREFUSED, ECONNRESET, ENOTFOUND, EPROTO) and fix accordingly.","Correct the `target` option (host:port/protocol) passed to startHTTPDirectProxy.","If ECONNRESET happens on long requests, disable upstream keep-alive/agent reuse or increase target server timeouts; retry the failed request."],"exampleFix":"// before: proxy points at a dead upstream\nawait startHTTPDirectProxy({ target: 'http://127.0.0.1:3000' }); // nothing listening → 500 Proxy error\n// after: verify/start target first, then proxy\nawait fetch('http://127.0.0.1:3000/health'); // ensure reachable\nawait startHTTPDirectProxy({ target: 'http://127.0.0.1:3000' });","handlingStrategy":"try-catch","validationCode":"// Before starting the proxy, verify the upstream target answers\nconst target = 'http://127.0.0.1:3000';\nawait fetch(target, { method: 'HEAD' }).catch((e) => {\n  throw new Error(`Upstream ${target} unreachable (${e.cause?.code ?? e.message}) — start it before proxying`);\n});","typeGuard":"function isProxyErrorBody(body: unknown): body is { error: 'Proxy error' } {\n  return typeof body === 'object' && body !== null &&\n    (body as any).error === 'Proxy error';\n}","tryCatchPattern":"// On the client side of the proxy, detect the 500 'Proxy error' response and inspect logs\nconst res = await fetch(urlThroughProxy);\nif (res.status === 500 && (await res.text()).includes('Proxy error')) {\n  // upstream failed: check '[HTTPProxy] Proxy error:' in CLI logs for ECONNREFUSED/ECONNRESET,\n  // then retry after confirming the target service is up\n}","preventionTips":["Always confirm the upstream target service is running and healthy before starting the proxy.","Double-check the `target` host/port/protocol passed to startHTTPDirectProxy.","Watch for ECONNRESET on long/streaming requests — adjust target keep-alive/timeouts.","Enable the proxy's verbose/log output so the underlying errno is captured when a 500 'Proxy error' appears."],"tags":["proxy","network","http","upstream"],"backgroundTag":"proxy-connection-refused","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}