bytedance/deer-flow · error · HTTPException

Token revoked (password changed)

Error message

Token revoked (password changed)

What it means

The token decoded and the user exists, but `user.token_version != payload.ver`: the password was changed (or sessions forcibly invalidated) after this token was issued, bumping the stored token_version. The token is deliberately rejected with HTTP 401 'Token revoked (password changed)'.

Source

Thrown at backend/app/gateway/langgraph_auth.py:97

            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


@auth.on
async def add_owner_filter(ctx: Auth.types.AuthContext, value: dict):
    """Inject user_id metadata on writes; filter by user_id on reads.

    Gateway stores thread ownership as ``metadata.user_id``.
    This handler ensures LangGraph Server enforces the same isolation.
    """
    # On create/update: stamp user_id into metadata
    metadata = value.setdefault("metadata", {})
    metadata["user_id"] = ctx.user.identity

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Re-authenticate: log in again with the current password to get a token carrying the new token_version
  2. If you administer the server and want sessions preserved across a password change, bump token_version only when forced logout is intended
  3. For automated clients, catch this specific 401 and trigger the login flow instead of retrying
Defensive patterns

Strategy: retry

Try / catch

try {
  await call();
} catch (e) {
  if (e.status === 401 && /Token revoked/.test(e.detail)) {
    await login();       // password changed elsewhere; get new token_version
    return await call();
  }
  throw e;
}

Prevention

When it happens

Trigger: Changing the account password while another browser/tab/session holds an older cookie; an admin force-logout that bumps token_version; any security event that rotates token_version.

Common situations: Password reset from a different device leaving stale sessions on others; bulk session invalidation after a security incident; tests reusing fixtures after password updates.

Related errors


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