Skip to content

fix(cubejs): guard express error handler against already-sent responses#49

Merged
acmeguy merged 1 commit intomainfrom
fix/cubejs-error-handler-headers-sent
Apr 23, 2026
Merged

fix(cubejs): guard express error handler against already-sent responses#49
acmeguy merged 1 commit intomainfrom
fix/cubejs-error-handler-headers-sent

Conversation

@acmeguy
Copy link
Copy Markdown

@acmeguy acmeguy commented Apr 23, 2026

Summary

  • Short-circuit the fallback error middleware with res.headersSentnext(err) in services/cubejs/index.js.
  • Prevents the handler from calling res.status().send() on a response whose headers have already been flushed.

Context

Observed in production logs on synmetrix-cubejs:

Error: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader ...
    at ServerResponse.send ...
    at file:///app/index.js:112:33
    at handleErrorMiddleware (/app/node_modules/@cubejs-backend/api-gateway/src/gateway.ts:2287:5)

The upstream cube api-gateway error handler already sends its own response, then forwards via next(err). The trailing app.use((err, req, res, next) => ...) in index.js then tries to write again and throws. This masks the original error (the surfaced message was a hasura auth rejection, not a header issue) and adds log noise.

Not the cause of any crash — cube's orchestrator handles the re-throw — but it's obscuring real errors.

Test plan

  • Trigger a 401 against /cubejs-api/v1/load with no auth, confirm response is still 403/401 (handled upstream) and no Cannot set headers line appears in logs.
  • Trigger a generic error from a custom route in src/routes/, confirm it still reaches this fallback handler and returns 500 with err.message.

🤖 Generated with Claude Code

The fallback error middleware called `res.status().send()` unconditionally,
which threw `Cannot set headers after they are sent to the client` when
upstream middleware (e.g. cube's api-gateway handler) had already
written the response. The thrown error masked the original stack.

Bail out via `next(err)` when `res.headersSent` so the default express
handler can finish tearing down the connection.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@acmeguy acmeguy merged commit 86b2b38 into main Apr 23, 2026
3 checks passed
@acmeguy acmeguy deleted the fix/cubejs-error-handler-headers-sent branch April 23, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants