slopus/happy · error

Proxy error

Error message

Proxy error

What it means

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'.

Source

Thrown at packages/happy-cli/src/modules/proxy/startHTTPDirectProxy.ts:25

    verbose?: boolean;
    onRequest?: (req: IncomingMessage, proxyReq: ClientRequest) => void;
    onResponse?: (req: IncomingMessage, proxyRes: IncomingMessage) => void;
}

export async function startHTTPDirectProxy(options: HTTPProxyOptions) {
    const proxy = httpProxy.createProxyServer({
        target: options.target,
        changeOrigin: true,
        secure: false
    });

    let requestId = 0;

    // Handle proxy errors
    proxy.on('error', (err, req, res) => {
        logger.debug(`[HTTPProxy] Proxy error: ${err.message} for ${req.method} ${req.url}`);
        if (res instanceof ServerResponse && !res.headersSent) {
            res.writeHead(500, { 'Content-Type': 'text/plain' });
            res.end('Proxy error');
        }
    });

    // Trace outgoing proxy requests
    proxy.on('proxyReq', (proxyReq, req, res) => {
        // const id = ++requestId;
        // (req as any)._proxyRequestId = id;
        
        // logger.debug(`[HTTPProxy] [${id}] --> ${req.method} ${req.url}`);
        // if (options.verbose) {
        //     logger.debug(`[HTTPProxy] [${id}] --> Target: ${options.target}${req.url}`);
        //     logger.debug(`[HTTPProxy] [${id}] --> Headers: ${JSON.stringify(req.headers)}`);
        // }
        
        // Allow custom request handler
        if (options.onRequest) {
            options.onRequest(req, proxyReq);

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Confirm the upstream `target` is running and reachable: `curl <target>` from the same machine; start/restart the target service if it's down.
  2. Check the CLI file logs for '[HTTPProxy] Proxy error: ...' to see the underlying errno (ECONNREFUSED, ECONNRESET, ENOTFOUND, EPROTO) and fix accordingly.
  3. Correct the `target` option (host:port/protocol) passed to startHTTPDirectProxy.
  4. If ECONNRESET happens on long requests, disable upstream keep-alive/agent reuse or increase target server timeouts; retry the failed request.

Example fix

// before: proxy points at a dead upstream
await startHTTPDirectProxy({ target: 'http://127.0.0.1:3000' }); // nothing listening → 500 Proxy error
// after: verify/start target first, then proxy
await fetch('http://127.0.0.1:3000/health'); // ensure reachable
await startHTTPDirectProxy({ target: 'http://127.0.0.1:3000' });
Defensive patterns

Strategy: try-catch

Validate before calling

// Before starting the proxy, verify the upstream target answers
const target = 'http://127.0.0.1:3000';
await fetch(target, { method: 'HEAD' }).catch((e) => {
  throw new Error(`Upstream ${target} unreachable (${e.cause?.code ?? e.message}) — start it before proxying`);
});

Type guard

function isProxyErrorBody(body: unknown): body is { error: 'Proxy error' } {
  return typeof body === 'object' && body !== null &&
    (body as any).error === 'Proxy error';
}

Try / catch

// On the client side of the proxy, detect the 500 'Proxy error' response and inspect logs
const res = await fetch(urlThroughProxy);
if (res.status === 500 && (await res.text()).includes('Proxy error')) {
  // upstream failed: check '[HTTPProxy] Proxy error:' in CLI logs for ECONNREFUSED/ECONNRESET,
  // then retry after confirming the target service is up
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/0a1a1875bbafa46f. Report an issue: GitHub.