Repository navigation
fix(native-chat): never refuse a user's write because the retry record is full - #26543
Conversation
…d is full The record that lets a retried chat write or agent launch replay instead of running twice refused every new write once it held 512 ids for one caller or 4,096 in total. Background agent traffic fills that in a normal day, so the user's own message was refused with "too many requests in the last day". Remove the count limit from the durable record, the in-memory launch record and the SSH relay's launch record; each entry still lives exactly as long as the retry window it protects. Clients still understand the refusal from older hosts, and its message now says to update Orca on that computer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… cover create records past the old cap
Review summaryThe problem. On 2026-10-08 the native-chat composer refused a message with "Orca has received too many requests in the last day. Your message was not sent." Orca keeps a one-day receipt for every chat write so a retry replays instead of running twice, and it refused all new writes once 4,096 receipts (or 512 from one sender) were held. Agents mailing each other through Orca filled that limit in a normal day (only 313 of the 4,096 were the user's own), so background traffic blocked the user, with nothing they could do but wait. The user-facing change. Chat sends, setting changes, answers and agent starts are no longer refused because of how many receipts exist. Retries still replay, a reused id with different contents is still refused, and an id older than the retry window is still refused. If a user's phone or desktop talks to an older Orca that still has the limit, the notice now says "Orca on the computer running this chat has hit a request limit. Update Orca there, then try again." Review. Three independent reviewers (correctness and compatibility, performance and runaway growth, and an architecture challenger who designed a fix from the problem alone before reading this one), then a review of the fix commit, then a release-readiness checklist. No P0, P1 or P2 issues. The architecture challenger arrived at the same design and agreed with keeping the database-backed receipt store as a separate follow-up, so this PR stays small enough to take into a release. Fixed during review
Deferred (follow-ups, not blockers)
What was verified
Not verified
Known residual risks (unproven, not blockers)
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (27)
💤 Files with no reviewable changes (5)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe durable operation ledger, Orca runtime, and PTY handler no longer reject new operations because of per-caller, global, or map-size limits. Tests cover admission beyond the former limits and replay of existing operations. Launch handling and capacity notices now treat Priority: ⬆️ High Merge Risk: ⚪ Minimal · up to Eligible writes and agent-session creates should no longer be refused solely because retry records reached the former limits. No actionable merge-blocking issue is established. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 15 files. (7 skipped: 7 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ELI5
ELI5
When you send a chat message, Orca writes down a receipt for it, so that if the send is retried (say the connection drops) Orca replays the first answer instead of sending the message twice. Orca kept those receipts for a day and allowed at most 4,096 of them in total, and at most 512 per sender. When the pile was full, Orca refused every new message until old receipts aged out. Agents talking to each other through Orca fill that pile in an ordinary day, so a user's own message was refused with "Orca has received too many requests in the last day. Your message was not sent." This removes the limit: a receipt still lasts exactly as long as a retry can arrive, and nothing refuses a message because the pile is big.
What Changed
Before: on a busy day of multi-agent work, the composer refused the user's message (and setting changes, answers, and new agent launches) with "Orca has received too many requests in the last day." Nothing the user could do fixed it except waiting up to a day. Seen live on 2026-10-08: the receipts table held exactly 4,096 rows; the user's own sends were 313 of them, and the rest came from orchestration mail between agents, agent starts, and restart continuations, arriving at roughly 200 to 300 per hour. The same refusal also stopped agents from starting worker chats that night.
After: writes are never refused because of how many receipts exist. Retries still replay their recorded answer, a reused id with different contents is still refused, and an id older than the retry window is still refused rather than run again.
Mechanism. Three places counted retry records and refused new work at a fixed count:
src/shared/agent-session-operation-ledger.ts): 512 per caller, 4,096 total;terminal.createAgentSession,src/main/runtime/orca-runtime-create-agent-session.ts): the same limits;src/relay/pty-handler.ts): 4,096.All three count limits are removed. Each record's lifetime is unchanged: it lives for the window in which a retry of its id could still arrive, and is pruned after that. The relay's separate limit on how many terminals can run at once is a real resource bound and is unchanged.
Older hosts. A paired Orca server or desktop that hasn't updated (for example, a phone talking to an older desktop) still sends this refusal. Clients keep understanding it, and the message now gives the user something to do: "Your message was not sent. Orca on the computer running this chat has hit a request limit. Update Orca there, then try again." (translated in every catalog).
Removed dead code. The desktop's agent-launch path had a fallback that re-ran a launch without a receipt when its own host refused with this limit. That launch always goes to the window's own main process, which ships in the same build and can no longer refuse this way, and an SSH relay of a different version can't connect at all, so the fallback is gone. If the refusal ever arrived anyway, the launch is reported as not started like any other refused launch.
Why
The limit existed to bound memory: a receipt can't be dropped early, or a late retry of it would run the work a second time. But enforcing that bound by refusing new work made unrelated background traffic block the user, and the user had no way to clear it. The common pattern for retry receipts keeps a receipt per command and replays it on a duplicate, with no count limit and no refusal when there are many.
Alternatives considered:
Cost without the limit. Measured on the live table: about 235 writes an hour on a busy multi-agent day, so about 5,600 receipts held at once (the old limit was suppressing some of that, so real demand may be a little higher). At that size a send spends about 2 to 3 ms of main-process time on receipt bookkeeping and the receipts take about 3.5 MB of memory. It grows linearly: about 9 ms per send at 20,000 receipts. Removing the limit also removed two per-caller counting scans from every admission. No Orca producer mints new ids in a retry loop; the one way to multiply rows is agents mailing a chat whose message queue is full (about one row per message), which is being fixed separately.
Differences from the common pattern, labelled:
Linked Issue
N/A, found in live use on 2026-10-08.
Visual Proof
Hidden test build on macOS, with a fresh profile whose receipts table was seeded to 4,096 unexpired rows from fake orchestration callers (as on the machine where this was found), then the same message sent in a native chat.
Before (base build): the send is refused, the text goes back into the composer, and the agent never receives it. The table stays at 4,096 rows.
After (this PR): the same send goes through and the agent answers; the table grows past 4,096.
After, a second send (and a composer setting change, not pictured) also go through; the table holds 4,100 rows.
Testing
src/shared/agent-session-operation-ledger.test.ts: a fresh id is admitted with 5,600 unexpired rows held by other callers and 600 by the same caller, and a retry of an earlier id still replays. This fails onmain.src/main/runtime/rpc/methods/agent-launch-restart-replay.test.ts: a desktop agent launch starts with 600 unexpired operations already recorded for the desktop. Before, this was refused at 512.src/main/runtime/orca-runtime-agent-session-operation.test.ts: 4,097 creates from one caller all start, and a retry of the first still replays (fails with either old limit restored).src/relay/pty-handler-spawn-admission.test.ts: the relay starts a new create with 4,096 records held and still replays an earlier one (fails with the old limit restored).src/main/native-chat/agent-session-wire/structured-agent-session-refusal-retry.test.ts: the census of refusals the host can produce now lists the capacity refusal as not produced by this host.src/shared/agent-session-refusal-notice.test.ts,use-structured-agent-session-options.test.tsx: the new wording, and that "try again" appears only where updating Orca is the fix.Also ran:
structured-agent-session-send-evidence.test.ts,agent-launch-through-host.test.ts,launch-agent-new-tab-host-route*.test.ts,structured-mailbox-pointer-host.test.ts. Typecheck: node, web and cli projects. Localization catalog, extraction and coverage checks.Electron check (hidden window, driven by an automated agent): the before/after above.
I manually tested these changes locally
Automated tests added/updated, or explained why not below
Review
Agent skill upstream boundary
Notes
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)Author: @BrennanKB5