Repository navigation
Commit 5f3e46c
fix: don't reuse disabled proxy key on workflow re-runs; non-fatal title-gen errors (#636)
* fix: don't reuse disabled proxy key on workflow re-runs; non-fatal title-gen errors
Three small surgical fixes addressing run https://github.com/pullfrog/app/actions/runs/25580969379:
1. **`/api/proxy-token` idempotency now checks `finalizedAt`.** GitHub re-runs
share the same `run_id` (only `run_attempt` increments), so attempt N+1's
action calls /api/proxy-token and inherits attempt N's `proxyKeyId`. The
`workflow_run.completed` webhook between attempts retires that key on
OpenRouter (`disableKey`), so attempt N+1 was getting back a disabled key
and OpenRouter responded with `401 User not found` on every call. Falling
through when finalized routes through the same billing gate
(`handleRouterBilling` balance check), so no new attack surface.
2. **OpenCode title-gen / small-model errors no longer fatal.** OpenCode
auto-spawns a small `agent=title small=true` background call at session
start to name the thread, defaulting to `anthropic/claude-haiku-4.5`
(anomalyco/opencode#1243). Pre-fix, the wrapper's `error` event handler
treated any `type=error` as fatal, so a cosmetic title failure killed the
run before primary inference even started. Now: stderr matching `small=true`
sets a one-shot suppression flag for the next stdout `error` event, which
is logged as a warning instead.
3. **Provider-error classifier puts auth patterns above rate-limit.** OpenRouter
401 payloads bundle `x-ratelimit-*` response headers, and the loose
`\brate[_ ]limit/i` pattern was winning. Added 401/403 status, `User not
found`, `Invalid authentication`, `No auth credentials found` patterns
ahead of rate-limit. Updated the existing 401-headers regression test to
assert correct auth classification rather than `null`.
* opencode: correlate small-model error suppression by message, not by next-event
Pullfrog self-review on #636 flagged a real concurrency hole. OpenCode forks
the title-gen call (`session/prompt.ts:1452-1457` via `Effect.forkIn(scope)`)
so it races primary inference. The previous one-shot `suppressNextErrorEvent`
boolean had no per-call correlation: it was consumed by whichever stdout
`type=error` event landed next, regardless of which subagent produced it.
Under concurrent failures, a primary-agent error landing first could be
silently downgraded to a warning while the small-model error then propagated
fatally — the inverse of the bug the suppression was meant to prevent.
Replaced the boolean with a `Set<string>` of pending small-model error
messages. stderr extracts the inner `"message":"..."` from any classified
provider error tagged `small=true`; the stdout `error` handler suppresses
only when `event.error.data.message` matches a pending entry. Set is capped
at 32 entries so a long stream of small-model failures can't wedge memory.
Also corrected the comment that referenced "session summarizer" — verified
in opencode source that summarize() does NOT use `small: true`; only the
title generator does today (only `small: true` match in the codebase).
* revert: drop opencode title-gen suppression
We have no evidence — and can't construct a realistic scenario — where
title-gen fails on an otherwise-successful run. Title-gen and primary share
the same OPENROUTER_API_KEY and hit the same proxy/upstream; whatever breaks
one breaks the other. The original repro on run 25580969379 is fully
explained by the stale proxy key (fix #1) — title-gen happened to be the
first call that surfaced the auth error, but every subsequent primary call
would have died the same way.
Suppression code adds complexity (cross-stream correlation logic, message
matching, set capping) and a real failure mode of its own (a small-model
error with a unique message could mask an unrelated primary error landing
shortly after). Net negative. Removing.1 parent 3d393c3 commit 5f3e46c
2 files changed
Lines changed: 50 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
11 | 17 | | |
12 | 18 | | |
13 | 19 | | |
| |||
16 | 22 | | |
17 | 23 | | |
18 | 24 | | |
19 | | - | |
| 25 | + | |
20 | 26 | | |
21 | 27 | | |
22 | 28 | | |
| |||
29 | 35 | | |
30 | 36 | | |
31 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
32 | 69 | | |
33 | 70 | | |
34 | 71 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
9 | 20 | | |
10 | 21 | | |
11 | 22 | | |
| |||
0 commit comments