cube-js/cube · error
e.toString()
Error message
e.toString()
What it means
In the API Gateway auth error path (packages/cubejs-api-gateway/src/gateway.ts:2868), when token authorization throws an unexpected error, the handler logs 'Auth Error' and responds 500 with { error: e.toString(), stack }. The thrown value's stringification is surfaced verbatim to the client, which usually indicates a non-Error throw or a misconfigured JWT secret/checker rather than a normal 401 auth rejection.
Source
Thrown at packages/cubejs-api-gateway/src/gateway.ts:2868
const error = e.originalError || e;
const stack = getEnv('devMode') ? error.stack : undefined;
this.log({
type: error.message,
url: req.url,
token,
error: stack || error.toString()
}, <any>req);
res.status(e.status).json({ error: e.message });
} else if (e instanceof Error) {
const stack = getEnv('devMode') ? e.stack : undefined;
this.log({
type: 'Auth Error',
token,
error: stack || e.toString()
}, <any>req);
res.status(500).json({
error: e.toString(),
stack,
});
}
}
}
protected checkAuth: RequestHandler = async (req, res, next) => {
await this.checkAuthWrapper(this.checkAuthFn, req, res, next);
};
protected checkAuthSystemMiddleware: RequestHandler = async (req, res, next) => {
await this.checkAuthWrapper(this.checkAuthSystemFn, req, res, next);
};
protected requestContextMiddleware: RequestHandler = async (req: Request, res: ExpressResponse, next: NextFunction) => {
try {
req.context = await this.contextByReq(req, req.securityContext, getRequestIdFromRequest(req));View on GitHub (pinned to 7d981676b3)
Solutions
- Check the returned `error`/`stack` in the 500 body to identify the underlying exception
- Verify the client's JWT is signed with the same secret as CUBEJS_API_SECRET and uses a supported algorithm
- Make any custom checkAuth/securityContext functions throw standard Errors and return 401 for auth failures instead of letting exceptions escape
- Regenerate/reissue tokens if the secret was rotated
Example fix
// before (custom auth that throws)
checkAuth: (req, auth) => { if (!auth) throw new Error('no auth'); }
// after
checkAuth: async (req, auth) => { if (!auth) throw new AuthenticationError('no auth'); } Defensive patterns
Strategy: try-catch
Validate before calling
function isWellFormedJwt(token) {
return typeof token === 'string' && token.split('.').length === 3;
} Type guard
function isAuthError(e: unknown): e is Error {
return e instanceof Error && 'name' in e;
} Try / catch
// client-side
try {
const res = await cubejsApi.load(query);
} catch (e) {
if (e?.response?.status === 500 && e.response.data?.error) {
console.error('Auth path threw:', e.response.data.error, e.response.data.stack);
}
} Prevention
- Ensure client JWTs are signed with the same secret/algorithm as CUBEJS_API_SECRET
- Have custom checkAuth/securityContext hooks throw standard Errors and map auth failures to 401
- Rotate and redeploy secrets atomically so old tokens fail with clear errors, not exceptions
- Log the stack field from the 500 body to pinpoint the throwing auth code
When it happens
Trigger: A request with an auth token where the token check throws — e.g. jwt.verify failing with a non-standard error, a custom checkAuth function throwing, or a wrong/malformed CUBEJS_API_SECRET causing an exception in the auth path.
Common situations: Mismatched JWT signing secret between client and Cube; expired/malformed tokens handled by custom auth code that throws; auth functions written async but consumed synchronously, causing unhandled rejections surfacing here.
Related errors
- Unable to decode JWT key
- JWT without kid inside headers
- Unable to verify, JWK with kid: "${decoded.header.kid}" not
- Invalid token
- Authorization header isn't set
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/d98f4ca3437149b2.
Report an issue: GitHub.