bytedance/deer-flow · error · HTTPException
Invalid token
Error message
Invalid token
What it means
The `access_token` cookie was present but `decode_token` returned a `TokenError`, meaning the JWT failed decode/validation (bad signature, malformed, or expired). The handler immediately raises HTTP 401 with detail 'Invalid token'. It is distinct from a missing cookie (120) and from a revoked-but-valid token (123).
Source
Thrown at backend/app/gateway/langgraph_auth.py:85
Also enforces CSRF on state-changing methods.
"""
# CSRF check before authentication so forged cross-site requests
# are rejected early, even if the cookie carries a valid JWT.
_check_csrf(request)
if is_auth_disabled():
return AUTH_DISABLED_USER_ID
token = request.cookies.get("access_token")
if not token:
raise Auth.exceptions.HTTPException(
status_code=401,
detail="Not authenticated",
)
payload = decode_token(token)
if isinstance(payload, TokenError):
raise Auth.exceptions.HTTPException(
status_code=401,
detail="Invalid token",
)
user = await get_local_provider().get_user(payload.sub)
if user is None:
raise Auth.exceptions.HTTPException(
status_code=401,
detail="User not found",
)
if user.token_version != payload.ver:
raise Auth.exceptions.HTTPException(
status_code=401,
detail="Token revoked (password changed)",
)
return payload.sub
View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Re-login to mint a fresh token cookie
- If tokens expire immediately, verify the token TTL and server clock (NTP) are sane
- If all clients fail after a deploy, check whether the signing secret changed and either restore it or force re-login for all users
- Ensure every Gateway replica/instance shares the same signing secret
Defensive patterns
Strategy: retry
Try / catch
try {
await call();
} catch (e) {
if (e.status === 401 && /Invalid token/.test(e.detail)) {
await login(); // mint a fresh cookie
return await call(); // single retry
}
throw e;
} Prevention
- Refresh/re-login proactively when the token nears its TTL instead of waiting for 401s
- Keep the JWT signing secret identical across replicas and redeploys
- Distinguish this 401 (bad token) from the no-cookie 401 — only the former implies secret/expiry drift
When it happens
Trigger: Presenting an expired JWT cookie; a token signed with a different/rotated secret (server secret changed or multi-instance mismatch); a truncated or tampered cookie value; clock skew pushing the expiry check over the edge.
Common situations: JWT secret rotated during redeploy while browsers held old cookies; AUTH_SECRET env var differing between Gateway replicas; long-lived browser sessions after token TTL elapsed with no refresh path; manually editing or re-serializing the cookie.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Token error: {payload.value}
- USER_NOT_FOUND
- TOKEN_INVALID
- Failed to read JWT secret from {secret_file}. Set AUTH_JWT_S
- Failed to persist JWT secret to {secret_file}. Set AUTH_JWT_
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/40ae54b10e20a50d.
Report an issue: GitHub.