Repository navigation
fix(sse): skip already-refused route per request on 429 - #13795
Merged
diegosouzapw merged 8 commits intoSep 16, 2026
Merged
Conversation
maxmad64bis
force-pushed
the
feat/n90-dedup-cid
branch
2 times, most recently
from
September 15, 2026 20:52
49f9679 to
890ab2f
Compare
maxmad64bis
force-pushed
the
feat/n90-dedup-cid
branch
from
September 15, 2026 20:55
890ab2f to
b228aa6
Compare
maxmad64bis
marked this pull request as ready for review
September 15, 2026 20:57
A request never re-sends to a route the upstream just refused with 429: record the refused route key in the request-local tried set on the 429 arm (mirror of the 5xx/geo arms). Fail-open preserved via the existing fallback; a refused direct route (null key) records nothing.
maxmad64bis
force-pushed
the
feat/n90-dedup-cid
branch
from
September 15, 2026 23:57
b228aa6 to
b6cd809
Compare
…ailures (diegosouzapw#13615) Behind the new `OPENCODE_TRANSIENT_FAILOVER_BACKOFF` flag (default off), after two consecutive transient upstream failures the opencode rotation pauses before each later account (1.5s, 3s, 6s, capped at 10s per request) instead of hammering the upstream. Maintainer rework before merge (kept the idea, no default behavior change): - The pause honors the client abort signal (no dispatch after a disconnect), the failed attempt's body is cancelled before sleeping, `transientRetryDelayMs` now uses its arguments, and the sleep is injectable so the tests run without real timers. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…o clear auth failure (diegosouzapw#13609) Behind the new `MISTRAL_AMBIGUOUS_401_SOFT_LOCKOUT` flag (default off), a bare Mistral 401 (`{"detail":"Unauthorized"}`, identical for a revoked key and an exhausted quota) gets a retryable cooldown instead of parking the connection as `expired`; after three soft strikes within an hour the next bare 401 parks it, so revocation still converges. Maintainer rework before merge (kept the idea, no default behavior change): - The predicate is shared with the connection-test module instead of duplicated; the squeezed 139-char line that dodged the file-size gate is formatted normally and the growth is rebaselined honestly with an annotation. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…d ERROR_TYPE_CONTRACT import left by the batch merges (diegosouzapw#13816) Merged with admin on local + CI evidence: `tests/unit/i18n-catalogs-no-duplicate-keys.test.ts` red on the tip (59 catalogs) → `pass 3 / fail 0` here; **API Route Typecheck passes on this PR** (it fails on every PR based on the current tip because of the duplicated `ERROR_TYPE_CONTRACT` import this removes); CodeQL, semgrep, Vitest fast-path, Docs gates, Change Classification pass. The remaining red checks (Fast Quality Gates, Merge integrity, Unit Tests fast-path 1/2/4) are the same inherited tip reds every PR on release/v3.8.51 shows right now — diegosouzapw#13747 sweeps them. Both removed lines were byte-identical duplicates; nothing parsed or typed changes.
…gosouzapw#13657) The opencode executor classifies rate-limited 429 bodies (`classify429`, with real tests) and, when a whole account wave is exhausted, returns the last real upstream 429 — status, body, `Retry-After` and quota headers intact — so the provider error rules (monthly-quota cooldown) keep working. Maintainer rework before merge (kept the idea, no default behavior change): - The original stopped the cross-account wave at the first classified 429 and replaced the response with a synthetic one that dropped the body and headers; stopping early is now opt-in behind `OPENCODE_RATE_LIMITED_429_EARLY_STOP` (default off), the rate-limited account is still cooled down, the body is read as a bounded 8 KiB prefix from a clone and the original is never consumed, and the unused `status` input is gone. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…(stryker, CLI i18n, paid-target fixture, call-log traceId, Jina prefix, callLogStats import, gitleaks) (diegosouzapw#13747) * fix(ci): clear the release/v3.8.51 base-reds left by the 09-15 batch — stryker coverage, CLI ready_timeout key, paid-target fixture, call-log traceId, Jina custom prefix Every PR into release/v3.8.51 pushed after diegosouzapw#13635/diegosouzapw#13678 still failed Fast Quality Gates and all four Unit fast-path shards on the same 16 tests. Each one reproduces on the pure tip; none is a product defect: - mutation-test-coverage: noauth-model-lockout and local-token-budget-429-skips-cooldown (diegosouzapw#13606) were missing from stryker.conf.json tap.testFiles. - cli-i18n-catalog: --ready-timeout calls t("serve.ready_timeout") with no catalog entry; added to en, zh-CN and zh-TW (the parity-checked locales). - paid-model-target(-routes)-6540: diegosouzapw#13407 removed Together's one-time credit from the free catalog, so "together/..." classifies as unknown and the save-time guard correctly lets it through. Fixture is now gemini/gemini-3.1-pro-preview, plus a precondition test on the fixtures. - attempt-logging-early-keepalive-merge / video-bridge-log-redaction: diegosouzapw#13546 keys the call-log row on traceId; baseCtx now defaults traceId to pendingRequestId (same pattern as chatcore-attempt-logging). The keepalive test also moves to the 30s wall-clock poll deadline video-bridge uses. - models-catalog-route: custom Jina rows keep the jina-ai/ prefix; diegosouzapw#13403 changed the custom assertion to jina/ (only synced rows use the alias). Refs diegosouzapw#12732 * fix(ci): clear the four reds the first r4 CI run surfaced — callLogStats duplicate import, Uzbek gitleaks false positive, redaction probe traceId, file-size - src/lib/db/callLogStats.ts: the diegosouzapw#13641 merge left ERROR_TYPE_CONTRACT imported twice (TS2300), failing API Route Typecheck and check:dashboard-typecheck on every PR. - .gitleaks.toml: the Uzbek catalog from diegosouzapw#13727 translates outputTokenDesc as "Yakunlash/javob tokenlari"; generic-api-key reads it as a token value. - dashboard-request-failed-redaction-probe: reads the persisted row by traceId (diegosouzapw#13546); with pendingRequestId it asserts null. - models-catalog-route: drop the explanatory comment, which pushed the frozen file over its size cap; the rationale lives in the changelog fragment. Refs diegosouzapw#12732 * fix(ci): re-freeze the two test files diegosouzapw#13748/diegosouzapw#13749 grew past their file-size caps PR-mode check:file-size relaxes source files against the base but not testFrozen, so image-generation-handler.test.ts (2133->2235, diegosouzapw#13748) and batch_api.test.ts (1345->1348, diegosouzapw#13749) failed Fast Quality Gates on every PR, this one included. Caps set to the merged LOC, with the justification entry. Refs diegosouzapw#12732 * fix(ci): register free-badge-provider-gate (diegosouzapw#13645) in stryker tap.testFiles diegosouzapw#13645 landed a covering test for src/sse/services/auth.ts without the stryker entry, so the strict mutation-test-coverage gate went red again. Refs diegosouzapw#12732 * fix(ci): clear two more base-reds the diegosouzapw#13440/diegosouzapw#13439 merges added - stryker.conf.json: register daily-reset-tz-threading (diegosouzapw#13440), which covers accountFallback.ts and rrState.ts. - .gitleaks.toml: allowlist the PROTECTED_PRIORITY_INFRA_502_ENABLED flag id (diegosouzapw#13439); generic-api-key reads its key: as a token (secrets ratchet 0 -> 1). Refs diegosouzapw#12732 * docs(changelog): tidy the stryker base-red fragment wording Refs diegosouzapw#12732
…; ratio gate now blocking (diegosouzapw#13782) PR-4 of the locale-expansion plan. 215,363 strings retranslated across the 65 catalogs with the new `sync-ui-keys --retranslate-identical`; the share of leaves still identical to English drops from a mean of 18.3 % to 1.8 % (Spanish 56 → 2.1). No `__MISSING__` marker or missing key is left; zh glossary normalised; pinned product/flag names kept English and allowlisted. Baseline tightened and the CI step `i18n real-translation ratio` is blocking from here on.⚠️ base-red inherited: diegosouzapw#12732
diegosouzapw
merged commit Sep 16, 2026
d4835c5
into
diegosouzapw:release/v3.8.51
3 of 7 checks passed
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…#13795) On a 429 the opencode executor now records the refused proxy's key in the request-local tried-set, exactly like the 403/451, 5xx, stall and network arms already did — so a second account sharing that same proxy is not dialed and refused again before the loop reaches a genuinely different route (direct, or another proxy). Reviewed against the tip that already carries your 38 merges from this evening: this is additive to the flags that landed today (`OPENCODE_RATE_LIMITED_429_EARLY_STOP`, `PROXY_SKIP_RECENTLY_FAILED`, `OPENCODE_USER_BLOCKED_ROTATION`, `OPENCODE_TRANSIENT_FAILOVER_BACKOFF`) and does not double-skip when combined with them; direct accounts have a null proxy key and correctly record nothing. Validated as a combined board first (this PR merged with the 11 siblings of the same batch on the release tip): eslint on every changed file with the suppressions file, typecheck:core, check:open-sse-typecheck, complexity, cognitive-complexity, changelog-integrity, i18n new-key coverage, docs-sync, migration-numbering, provider-consistency and a duplicate-identifier audit all green, plus 275 passing / 0 failing focused node:test cases across the 28 test files the batch touches. Then re-validated alone on the fresh tip before this merge: conflicts re-resolved, file sizes rebaselined for this PR's own growth, eslint and this PR's focused tests re-run. Thanks @maxmad64bis!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A request can be re-sent to a route the upstream just refused with a 429, delaying the surfaced upstream error. The dispatch loop now records each refused route for the running request and moves on, so a refused route is tried once per request. Fully excluded requests return the last upstream error through the existing drain path.
Related Issues
5xx/cut)Validation
npm run lintTests Added Or Updated
tests/unit/opencode-429-proxy-dedup.test.ts(3 tests green: refused route tried once, fully excluded request drains last error, distinct routes tried twice)Coverage Notes
open-sse/executors/opencode.tscovered by the new test (refused-route record on the 429 arm, fail-open drain, no over-exclusion).Reviewer Notes
open-sse/executors/opencode.ts:585-587,699-707); predicate, guard, drain and cooldowns byte-identical. A refused direct route records nothing. No flag: the change only stops re-serving refused routes, it adds no retry wave. Coordination with open fix(sse): stop retry wave on rate-limited 429 and drain 429 once #13657 (same arm, no code dependency either way — a recorded key before a possible break is a dead write): suggested order is landing this first.API Route Typecheckred is inherited (src/lib/db/callLogStats.ts TS2300, untouched by this PR — same failure on base and on sibling fix(sse): stop unhydrated compatible connections routing to the real OpenAI/Anthropic API (#13452) #13798). Follow-up idea (not in scope): tighten the fully-excluded assertion to an exact count and add a direct-route case.