{"record":{"id":"3ddb890a68421c41","repo":"bytedance/deer-flow","slug":"token-error-payload-value","errorCode":null,"errorMessage":"Token error: {payload.value}","messagePattern":"Token error: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":401,"severity":"error","filePath":"backend/app/gateway/deps.py","lineNumber":762,"sourceCode":"        AUTH_SOURCE_SESSION,\n        AUTH_SOURCE_AUTH_DISABLED,\n        AUTH_SOURCE_INTERNAL,\n    }:\n        return state_user\n\n    from app.gateway.auth import decode_token\n    from app.gateway.auth.errors import AuthErrorCode, AuthErrorResponse, TokenError, token_error_to_code\n\n    access_token = request.cookies.get(\"access_token\")\n    if not access_token:\n        raise HTTPException(\n            status_code=401,\n            detail=AuthErrorResponse(code=AuthErrorCode.NOT_AUTHENTICATED, message=\"Not authenticated\").model_dump(),\n        )\n\n    payload = decode_token(access_token)\n    if isinstance(payload, TokenError):\n        raise HTTPException(\n            status_code=401,\n            detail=AuthErrorResponse(code=token_error_to_code(payload), message=f\"Token error: {payload.value}\").model_dump(),\n        )\n\n    provider = get_local_provider()\n    user = await provider.get_user(payload.sub)\n    if user is None:\n        raise HTTPException(\n            status_code=401,\n            detail=AuthErrorResponse(code=AuthErrorCode.USER_NOT_FOUND, message=\"User not found\").model_dump(),\n        )\n\n    # Token version mismatch → password was changed, token is stale\n    if user.token_version != payload.ver:\n        raise HTTPException(\n            status_code=401,\n            detail=AuthErrorResponse(code=AuthErrorCode.TOKEN_INVALID, message=\"Token revoked (password changed)\").model_dump(),\n        )","sourceCodeStart":744,"sourceCodeEnd":780,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/deps.py#L744-L780","documentation":"HTTP 401 raised when the access_token cookie exists but decode_token() returns a TokenError (malformed JWT, bad signature, expired, unknown algorithm, invalid claims). The specific TokenError value is mapped via token_error_to_code() into the AuthErrorResponse code and surfaced in the message as 'Token error: <value>'.","triggerScenarios":"Any authenticated call with a present-but-invalid JWT cookie: token signed with a rotated secret, token past its exp, tampered payload, or a token issued by a different issuer. The exact TokenError variant is echoed in the detail message.","commonSituations":"JWT secret (AUTH_SECRET or equivalent) rotated or regenerated after a restart, invalidating all outstanding cookies; clock skew between issuer and verifier causing premature expiry; stale cookie from an old deployment left in the browser; manually edited cookie.","solutions":["Read the echoed TokenError value in the 401 detail — EXPIRED means just re-login; SIGNATURE/BAD_SIGNATURE means the secret rotated and all clients must re-login","Log in again to mint a token under the current secret; clear the stale cookie first if the login flow does not overwrite it","If signature errors affect everyone right after deploy, confirm the JWT secret is persisted (not randomly generated per-process) in your deployment config","Fix clock skew (NTP) if tokens fail as expired immediately after issuance"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"catch (e) {\n  if (e.status === 401 && e.detail?.message?.startsWith('Token error:')) {\n    clearSession(); goToLogin();  // any token-level failure is unrecoverable client-side\n    return;\n  }\n  throw e;\n}","preventionTips":["Persist the JWT signing secret across restarts (volume/env), never regenerate per boot","Keep server clocks NTP-synced to avoid premature token expiry","Treat all TokenError variants the same: clear cookie, re-authenticate"],"tags":["auth","http-401","jwt","token-expiry","secret-rotation"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}