Skip to content

(Bug/Discussion) Web session revoked (40003 INVALID_TOKEN) minutes after a short agent burst hits 429 "Messages too frequent" #105

Open

Description

@DataGeekMaster

(Bug/Discussion) Web session revoked (40003 INVALID_TOKEN) minutes after a short agent burst hits 429 "Messages too frequent"

Summary

When deeperseeker is used as the backend for a tool-calling agent, a single ordinary agent turn (≈8 upstream messages in ~60 s) gets 429 Messages too frequent on the last call. A few minutes later, with no further upstream traffic, the token starts returning 40003 Authorization Failed (invalid token). The web session is gone for good: the browser session for that account is logged out too, and only a fresh login gives a working token.

v6 handles the aftermath well (the CHANGELOG mentions 40003 / "messages too frequent" surfacing as typed 401/429 + rotation; the scheduler from #32/#39 stops the old 429 retry storm). But nothing prevents the first 429. Judging by the timing below, the 429 is not just transient back-pressure: it looks like a strike that leads to the session being revoked.

Environment

  • deeperseeker main @ 5fae265 (v6.0 + Harden upstream error handling: biz errors, count_tokens, stream truncation, setup retries #94), Python 3.13, bare metal (systemd), bound to 127.0.0.1
  • Client: an OpenAI-compatible agent framework (Hermes Agent) doing multi-step tool calls; streaming on
  • Server: AWS EC2, ap-southeast-3; default Android headers (no WAF cookie)
  • Accounts: email + password login, token copied from the web app
  • .env: DEEPSEEKER_RATE_LIMIT_COOLDOWN=300, DEEPSEEKER_TOKEN_CONCURRENCY=1
  • Local patch (small): when every token is cooling, pick_token() returns None instead of the soonest-to-recover token, so a 1-token pool does not re-send to an account that is still rate-limited. Without this, the soonest-to-recover fallback keeps hitting the same account.

Timeline (UTC, one token, "token B")

Time Event
03:36 Token B added, light use for ~9 h
03:49–03:54 (old pre-v6 build) repeated 429s on token B; old pick_token() instantly reset RATE_LIMITED → ACTIVE, so dozens of retries within seconds. Token survived.
06:45:21 429 on token B (no retry storm on v6)
12:43:20 Agent turn starts: 8 upstream calls in ~60 s (≈1 call / 7–8 s, normal tool-call pace)
12:44:21 Last call: SSE error event → HTTP 429: Messages too frequent. Try again later. → token B RATE_LIMITED 300 s
12:44 External health probe (GET /api/v0/users/current) on token B: code=0 (still valid)
12:44 → 12:58 No upstream requests: every client request was refused locally (pool cooling)
~12:58 GET /api/v0/users/current on token B → code=40003 msg=Authorization Failed (invalid token)

An older install (pre-v6) showed the same shape with a shorter delay: burst → 429 at 10:03:28 → 40003 at 10:06:03.

A second case that does NOT fit (token A)

Token A was added at 06:34 UTC, served ~12 requests successfully, and died at 06:45:09 on chat_session/create with code=40003 msg=INVALID_TOKEN. It never got a 429. So 429 is probably not the only trigger. Token A and token B are Gmail dot-variants of the same mailbox. We have not confirmed whether DeepSeek treats them as one account, but if it does, they share a frequency budget or a session limit.

What I think is happening (unconfirmed)

  1. DeepSeek's web backend seems to count "messages too frequent" events per account/session, and after some threshold (or with a delay) it revokes the session. Token B's earlier 429s that day may have counted toward that.
  2. Agent workloads hit this much sooner than chat workloads, because one user turn can be 5–15 upstream messages within a minute.

Proposal

An opt-in per-token sliding-window cap, enforced before sending, that waits rather than fails:

  • e.g. DEEPSEEKER_TOKEN_MAX_MSGS_PER_MIN=5 (unset = current behaviour)
  • the first N messages in a window go out immediately, so short tool chains stay fast; only messages beyond N wait for the window to slide
  • optional DEEPSEEKER_TOKEN_MAX_WAIT cap → after it, return 429 to the client instead of sending upstream
  • add the in-window count to /health or the dashboard

Also worth considering: make "refuse when every token is cooling" (instead of the soonest-to-recover fallback) a config option, because with a 1–2 token pool the fallback sends to an account that DeepSeek has just told to slow down.

Questions for maintainers / other users

  • Has anyone else seen 40003 follow a 429 by several minutes, especially with agent clients?
  • Does anyone know DeepSeek's real per-account message rate for the web app (messages/minute)?
  • Is there evidence that Gmail dot-variants map to the same DeepSeek account?

Happy to test a patch or share more (sanitized) logs.

Activity

  1. 1515asd commented on Nov 5, 2026

    @1515asd

    Just ran into this too. That 429 looks like a warning strike — shortly after, the account's web session gets revoked. Log into chat.deepseek.com with that account to see what's going on: if it says your login expired, the token is dead, sign in again and grab a fresh one. If you can log in but sending a message pops a mute notice, it'll show you how long the mute lasts — just wait until then.

  2. AmanCode22 commented on Nov 6, 2026

    @AmanCode22
    Owner

    @1515asd is this issue due to new policy update mute wave only?

  3. 1515asd commented on Nov 7, 2026

    @1515asd

    Not just the mute wave. From what we've traced, there are two separate mechanisms:

    1. Mutes — sending a message pops a mute notice with a duration. Account survives, just wait it out.
    2. Session-level revocation — what this issue reports: 40003 on the API token and the web session logged out at the same time. The session is killed server-side, not expired; only a fresh login brings it back.

    Two findings worth adding:

    • The 429 "Messages too frequent" looks like a warning strike — shortly after it, the whole session gets revoked, even with no further traffic. So after a 429 the safest move is to stop and back off immediately, not retry; hammering through it seems to escalate straight to revocation.
    • Revocation appears to be environment-based: sessions extracted in the browser and then used from a different environment get revoked the same way. That matches what you saw (the web session dying together with the token).

    So it's broader than the mute wave — the session revocation hits accounts that never got a mute notice at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions