Commit Graph

4 Commits

Author SHA1 Message Date
Fouad Salkini
fc6b240328 fix(oauth): classify an embedded invalid_grant in a refresh error body (#13466)
* fix(oauth): classify an embedded invalid_grant in a refresh error body

Cline answers a dead refresh_token with
400 {"data":"","error":"failed to refresh token: invalid_grant","success":false}
The code is the tail of a sentence — neither a bare code nor an
"error":"<code>" field pair — so extractOAuthErrorCode returned null.

A null classification means refreshClineToken emits no unrecoverable
sentinel, so a permanently consumed refresh_token is handled as a
TRANSIENT failure. tokenHealthCheck therefore never reaches its
unrecoverable branch, and never runs the credentialsChangedSinceSweep
race guard, the "please re-authenticate this account" message, or the
dead-token clear for rotating providers. The connection instead stays
active with errorCode "refresh_failed", retries the same consumed token
3x per sweep behind an exponential backoff, and 401s every request
routed to it indefinitely with no actionable operator signal.

Scan for a known unrecoverable code embedded in the error value as a
last resort, after the exact-match and nested-JSON paths, delimited on
both sides so server_error, xinvalid_grant, my_invalid_grant_flag and a
502 HTML page all still classify as null.

Also add cline to ROTATION_LOCK_GROUP: refreshClineToken reads a new
refreshToken out of every response body and a measured refresh rotated a
connection's stored token, so sibling connections must not refresh
concurrently. cline was already listed in tokenHealthCheck's
ROTATING_REFRESH_PROVIDERS but missing from the serializer.

* docs(changelog): add fragment for cline refresh token error classification

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-09-17 16:27:01 -03:00
backryun
13098989e8 fix(types): narrow refresh token rotation inputs (#10257) 2026-08-14 00:57:58 -03:00
backryun
65e0aeda79 [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider (#7866)
* refactor(cli): remove legacy Qwen Code integration

* refactor(qwen): remove deprecated Qwen OAuth provider

* feat(cli): rebuild Qwen Code integration for upstream V4

* fix(qwen): clear stale CLI auth on reset

* test(qwen): align retired provider coverage

* fix(db): renumber qwen-cleanup migration 129 -> 130

release/v3.8.49 tip took slot 129 via #7843 (usage_history_codex_strong_identity,
itself renumbered from 128 during the #7838/#7840 base-red cleanup) after this
branch forked; renumber remove_unregistered_qwen_data to 130.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
2026-07-20 17:53:04 -03:00
Hernan Javier Ardila Sanchez
fd26e601a2 fix(dashboard): use lightweight ping endpoint for MaintenanceBanner (fixes #3040) (#3043)
Integrated into release/v3.8.8. Applied review fixes: moved the SELECT 1 into a pingDb() db helper (no raw SQL in route, Hard Rule #5) + the 503 catch no longer leaks err.message (Hard Rule #12). Thanks @herjarsa!
2026-06-01 14:30:17 -03:00