bytedance/deer-flow · error · HTTPException

Token error: {payload.value}

Error message

Token error: {payload.value}

What it means

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

Source

Thrown at backend/app/gateway/deps.py:762

        AUTH_SOURCE_SESSION,
        AUTH_SOURCE_AUTH_DISABLED,
        AUTH_SOURCE_INTERNAL,
    }:
        return state_user

    from app.gateway.auth import decode_token
    from app.gateway.auth.errors import AuthErrorCode, AuthErrorResponse, TokenError, token_error_to_code

    access_token = request.cookies.get("access_token")
    if not access_token:
        raise HTTPException(
            status_code=401,
            detail=AuthErrorResponse(code=AuthErrorCode.NOT_AUTHENTICATED, message="Not authenticated").model_dump(),
        )

    payload = decode_token(access_token)
    if isinstance(payload, TokenError):
        raise HTTPException(
            status_code=401,
            detail=AuthErrorResponse(code=token_error_to_code(payload), message=f"Token error: {payload.value}").model_dump(),
        )

    provider = get_local_provider()
    user = await provider.get_user(payload.sub)
    if user is None:
        raise HTTPException(
            status_code=401,
            detail=AuthErrorResponse(code=AuthErrorCode.USER_NOT_FOUND, message="User not found").model_dump(),
        )

    # Token version mismatch → password was changed, token is stale
    if user.token_version != payload.ver:
        raise HTTPException(
            status_code=401,
            detail=AuthErrorResponse(code=AuthErrorCode.TOKEN_INVALID, message="Token revoked (password changed)").model_dump(),
        )

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. 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
  2. Log in again to mint a token under the current secret; clear the stale cookie first if the login flow does not overwrite it
  3. If signature errors affect everyone right after deploy, confirm the JWT secret is persisted (not randomly generated per-process) in your deployment config
  4. Fix clock skew (NTP) if tokens fail as expired immediately after issuance
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

catch (e) {
  if (e.status === 401 && e.detail?.message?.startsWith('Token error:')) {
    clearSession(); goToLogin();  // any token-level failure is unrecoverable client-side
    return;
  }
  throw e;
}

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/3ddb890a68421c41. Report an issue: GitHub.