Skip to content

fix(cursor): handle omitted subagent result fields - #26520

Closed
Zburgers wants to merge 1 commit into
pingdotgg:mainfrom
Zburgers:fix/cursor-subagent-result-projection
Closed

Zburgers wants to merge 1 commit into
pingdotgg:mainfrom
Zburgers:fix/cursor-subagent-result-projection

Conversation

@Zburgers

@Zburgers Zburgers commented Oct 28, 2026 •

Copy link
Copy Markdown

Problem

A completed Cursor subagent can include tool results serialized as protobuf JSON. Empty repeated fields may be omitted, but T3's Cursor adapter assumed they were present when projecting directory listings and other nested results. A projection exception was retained by the SDK runner while subsequent updates were discarded; when the run ended, the local callback error was reported as a run.wait transport failure.

Incident evidence

Persisted turn items from an affected run show the following sequence (UTC; worker names shortened):

2026-10-28T11:57:45.974Z  subagent completed  Worker A
2026-10-28T12:26:38.563Z  subagent failed     Worker B
2026-10-28T12:26:38.563Z  subagent failed     Worker C
2026-10-28T12:26:38.801Z  error failed
  class: transport_error
  message: Cursor Agent SDK run.wait failed: Cannot read properties of undefined (reading 'map')

The last recorded provider protocol update coincided with the Worker A completion, with no subsequent protocol output until the run ended. Two earlier occurrences had a completed subagent immediately before the same error. These timestamps support the observed sequence; the stored error has no stack trace identifying the exact throwing expression. The suspected ls path follows from inspecting the adapter's nested conversationSteps projection and reproducing omitted fields in tests. The logs alone do not establish that every long silent run has this cause.

Change

  • Treat omitted protobuf JSON arrays and default fields as empty when projecting nested Cursor tool results, including directory trees.
  • Continue processing later updates after a callback failure, retain the first failure, and report it as run.onDelta / provider_error rather than a transport failure.
  • Drain callbacks after run.wait() settles, including on rejection, and finalize early buffered callback failures without leaving the turn active.

This surfaces the failure when the provider run settles; it does not cancel the run immediately.

Validation

At head b261f1c530622a2c30d684cd2ee7b7dc159f7af7, pnpm exec vp run check:changed passed format, lint, both knip checks, typechecking for 10 affected packages, and both changed test files (21 tests). The tests cover omitted directory/result fields, continued delivery after a callback failure, buffered failure finalization, and an in-flight callback arriving after run.wait() starts. A separate Gemini 4 Argon review of this head reported no findings after its earlier callback-drain race finding was fixed.

The incident was inspected retrospectively; this change has not been exercised against the affected live Cursor session. Full CI suites and build remain for CI.

Separate incident

Separate backend logs record process exits with AbortError stacks in @cursor/sdk around cancellation. That process crash and the separately reported Workspace changed. errors are outside this PR; neither is established as the cause of the .map exception.

Fixes #26486

Naki’s 6.1 Terra

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Oct 28, 2026
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 5211acf and b261f1c.

Files selected for processing: 4
  • packages/provider-cursor/src/server/CursorAgentSdk.test.ts
  • packages/provider-cursor/src/server/CursorAgentSdk.ts
  • packages/provider-cursor/src/server/adapter.test.ts
  • packages/provider-cursor/src/server/adapter.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

The Cursor SDK session now continues dispatching queued deltas after callback failures and drains callbacks while waiting for the run. The adapter tolerates omitted tool-result fields and reports buffered callback failures as provider errors, while retaining transport classification for other SDK run failures.

Changes: Cursor provider handling

Layer / File(s) Summary
SDK callback lifecycle
packages/provider-cursor/src/server/CursorAgentSdk.ts, packages/provider-cursor/src/server/CursorAgentSdk.test.ts
The session processes queued callbacks after a callback failure and drains the callback chain while waiting for the run. Callback failures are reported as run.onDelta and take precedence over run-wait failures. Tests cover continued dispatch and a race between callback and run-wait failures.
Tool-result projection defaults
packages/provider-cursor/src/server/adapter.ts, packages/provider-cursor/src/server/adapter.test.ts
The adapter uses fallback values or empty collections when Cursor tool-result fields are omitted. Tests cover nested tool envelopes and empty file-search results.
Buffered callback failure handling
packages/provider-cursor/src/server/adapter.ts, packages/provider-cursor/src/server/adapter.test.ts
The adapter retains buffered interaction failures and finalizes a non-interrupted turn with a provider_error. Other SDK run failures remain transport_error failures.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related issues

  • #26486 — Covers omitted ls result arrays, later delta dispatch after callback failures, and callback error classification addressed by this change.

Possibly related PRs

  • pingdotgg/t3code#26262 — Changes the same Cursor SDK session wrapper and introduces the onDelta callback chain that this change extends.

Suggested reviewers: nkoynov

Merge Risk: Minimal · up to b261f

No merge-blocking issue is established; the change is ready for normal checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly identifies the Cursor fix and the omitted subagent result fields addressed by the pull request.
Linked Issues check Passed The changes satisfy the coding requirements in #26486. adapter.ts guards omitted ls roots, child arrays, and other omitted protobuf fields. CursorAgentSdk.ts continues the callback chain after a…
Out of Scope Changes check Passed The changed source and test files stay within #26486. The adapter changes support omitted Cursor tool fields and callback-failure handling. The SDK tests verify callback ordering and error precedence.…
Description check Passed The description is thorough and substantive. It states the problem, gives incident evidence with timestamps and the error text, explains the change in three bullets, and reports validation at a specif…
Full details: Linked Issues check

Explanation

The changes satisfy the coding requirements in #26486. adapter.ts guards omitted ls roots, child arrays, and other omitted protobuf fields. CursorAgentSdk.ts continues the callback chain after a callback failure and waits for the run and all callbacks before classifying the result. Callback failures use run.onDelta and become provider_error failures in the adapter. Tests cover omitted fields, continued dispatch, callback-versus-run.wait races, and provider-error classification.

Full details: Out of Scope Changes check

Explanation

The changed source and test files stay within #26486. The adapter changes support omitted Cursor tool fields and callback-failure handling. The SDK tests verify callback ordering and error precedence. No process-wide policy change or unrelated Workspace changed handling was added. The separate @cursor/sdk AbortError remains outside this pull request.

Full details: Description check

Explanation

The description is thorough and substantive. It states the problem, gives incident evidence with timestamps and the error text, explains the change in three bullets, and reports validation at a specific commit with the commands run and test counts. It links the fix to issue #26486 and separates the unrelated AbortError and Workspace changed issues. It does not follow the template's Scope and approval section: it links the issue but does not show a maintainer-approval comment or explain why the fix needs no prior approval. It also omits the model and harness line that the template asks for when an agent did the work. Those gaps are minor against the rest of the content, so the check passes.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@juliusmarminge juliusmarminge added bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed labels Oct 28, 2026

Copy link
Copy Markdown
Member

Thanks for this, and for the incident write-up in #26486.

We merged the projection half separately in #26592: nested ls, readLints and MCP results are now normalized where nestedToolCallFromEnvelope builds them, so the display code can keep relying on the SDK types. That covers the ?? [] / ?? "" changes in adapter.ts, and we'd rather not carry both.

The callback half is still open and nobody else is covering it: keep delivering updates after a callback failure, drain callbacks after run.wait() settles, and report the failure as run.onDelta / provider_error instead of transport_error. Could you rebase onto main and trim this PR to just that (CursorAgentSdk.ts, the error-class handling in the adapter, and their tests)?

One thing to check while you do: dropping the "skip after the first failure" guard means later updates run after one already threw partway through. A test showing a later update still projects correctly after an earlier one failed would cover that.

@t3dotgg

t3dotgg commented Oct 31, 2026

Copy link
Copy Markdown
Member

Note

🤖 Claude Opus 5.5 responding on behalf of Theo

Closing: this is covered by #26592, which landed. Reopen if a needed part is still missing.

@t3dotgg t3dotgg closed this Oct 31, 2026
@juliusmarminge juliusmarminge removed the pr:gate-failed A land gate failed label Oct 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Fix PR opened by an issue lead; enters the PR loop size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(cursor): tolerate omitted subagent tool result fields

3 participants