Repository navigation
[Provider compatibility] Cursor: incomplete tool-call streams poison conversation reuse #4874
Description
Client or integration
Codex App
Provider or upstream service
cursor
OpenCodex version
2.57.0
Endpoint or capability
/v1/responses Cursor protobuf tool calls
Current behaviour
On Codex Desktop through OpenCodex, Cursor models (including cursor/grok-4.6) talk Connect protobuf, not Responses. When a Cursor stream ends with a client tool still open, OpenCodex fail-closes:
Cursor stream ended with incomplete tool call(s)
That error is streamed. It is not thrown, so the overflow/invalid_argument remint ladder never runs. _cursorConversationId is assigned at the start of runTurn and persisted by continuationStateForResponse. The next turn reuses that id (or the deterministic thread hash). Cursor's side of the conversation is still waiting for mcpResult, so later turns in the same thread interrupt more often. Neighboring threads that never interrupted stay clean.
Native Composer replay also flushes unpaired toolCallStep history without a result, which looks like an interrupted attempt. External wire models such as grok-4.6 skip native mcpToolCall replay, so history repair alone cannot recover them; conversation remint is the path.
This is not a Cursor 429 / Ultra quota issue. The incomplete-tool event is a truncated stream, and CursorStreamTruncatedError is defined but never thrown.
Expected behaviour
Keep fail-closed on the current turn: do not emit a partial tool_call_start, and do not retry that send. After the incomplete-tool error is streamed, eligible non-isolated turns should remint the Cursor conversation id (same helper as overflow remint), persist the thread override for store:false clients, and invalidate the inherited checkpoint so the next turn does not resume a conversation left waiting for mcpResult. Isolated helper/compaction turns must not remint or donate that recovery to the parent.
Native Composer unpaired toolCallStep history should carry an honest [missing tool_result for this tool_use in history] placeholder (isError: true), matching Google #2199. External grok-4.6 stays on conversation remint.
Minimal redacted request or reproduction
Codex App -> local OpenCodex proxy -> cursor/grok-4.6 (or another Cursor model). Run a tool-using thread until the proxy reports Cursor stream ended with incomplete tool call(s), then continue the same thread. Later turns in that thread interrupt more often than a neighboring thread that never had a truncated tool stream.
Actual response or error
Cursor stream ended with incomplete tool call(s): <call id>. Arguments may be truncated; the call was not committed.
Subsequent turns in the same thread reuse the same Cursor conversation id and interrupt again.
Upstream documentation
No public Cursor Connect specification. The existing OpenCodex fail-closed path is finalizeTurnEvents in src/adapters/cursor/protobuf-events.ts. Overflow remint is the in-tree recovery helper this should reuse. Related repair: #2199 (Google missing tool_result). Distinct from xAI Responses adjacency (#4870 / #4871).
Suggested mapping or implementation notes
- Add
isCursorIncompleteToolCallMessageand flag that streamed error insrc/adapters/cursor.ts. - After
runOncereturns, remint viaremintConversationIdfor non-isolated turns. Do not retry the current send. - Native
conversationTurnsflush: unpairedpendingToolCallsgettoolCallStep(..., missingToolResult, codeMode). - Do not classify this as 429. Quota/rate cues stay on the existing overflow/rate path.
Additional context and attachments
Related: #2199, #3506, #1527, #4245, #4870 (xAI Responses, different adapter). Cursor 429 / empty-spin is a different failure and is not requested here.
Checks
- I searched existing provider and compatibility issues.
- The request and response were redacted.
- The expected behaviour is based on an upstream specification or a concrete client requirement.
Activity
Ingwannu commentedon Sep 17, 2026
Confirmed on current
dev(7868f5df5).finalizeTurnEvents()streams the incomplete-tool error, whilesrc/adapters/cursor.tsonly remints on the existing thrown overflow/cancel paths. Because the incomplete case is returned as an event, the conversation id and inherited checkpoint remain reusable on the next turn. Native replay also flushes pending tool calls without an honest missing-result placeholder.Draft PR #4875 addresses the two distinct boundaries without retrying the failed send: eligible non-isolated turns remint after the streamed incomplete-tool error and invalidate inherited checkpoint state, while native Composer history records an explicit missing
tool_result. Isolated helper/compaction requests remain fail-closed and do not donate recovery to the parent. Keeping this issue open until the PR is review-ready, its exact-head hosted CI is green, and the current head is approved.fix(cursor): remint conversation after incomplete tool-call streams (l…
fix(cursor): remint conversation after incomplete tool-call streams (#…
lidge-jun commentedon Sep 17, 2026
리뷰 · 우선순위 28 / 80
이 이슈는 Cursor Connect protobuf 경로에서 스트림이 열린 tool call을 남긴 채 끝나면 OpenCodex가 "Cursor stream ended with incomplete tool call(s)"를 흘리고, _cursorConversationId가 재사용되어 같은 스레드가 계속 깨진다는 내용이다. 보고 버전은 2.57.0, Cursor/grok-4.6을 포함한 Desktop 경로다.
현재 tip 41f1832(package 2.58.0)에는 이미 #4875 fix(cursor): remint conversation after incomplete tool-call streams (ee28833)가 들어가 있다. src/adapters/cursor.ts에 remintConversationId와 incomplete-tool-remint / incomplete-tool-remint-exhausted 진단이 보인다. 본문이 요구한 "overflow/invalid_argument remint ladder가 스트림 에러에는 안 돈다 → conversation remint"가 tip에 반영된 상태다.
이슈가 열린 채로 남은 이유는 merge 커밋에 Closes #4874가 없었거나 자동 종결이 안 된 것으로 보인다. 타임라인에는 #4875 cross-ref와 커밋 referenced만 있다. 인접 draft #4900(grok-4.6 tool-result echo)은 다른 잔여 증상이면 그쪽으로 이어가면 된다.
tip 기준 본문 재현 경로는 수정된 상태로 보는 것이 맞다. 2.57.0 보고 → tip 2.58.0+#4875. 재발을 보려면 tip SHA와 incomplete-tool-remint 로그를 새 이슈에 붙이면 된다.
라인 432 - src/adapters/cursor.ts remintConversationId
라인 553 - src/adapters/cursor.ts incomplete-tool-remint 진단
경로/심볼 - ee28833 / #4875: tip 랜딩. 이 이슈 본문 픽스
경로/심볼 - #4900: tip 이후 Cursor grok-4.6 echo 잔여가 있으면 별도 추적
메인테이너의 판단이 필요한 지점
너의 추천
Fixed by #4875 (ee28833) on dev @41f1832f6 로 close. 잔여 echo는 #4900만 본다. 라벨은 바꾸지 않는다.
이 댓글은 grok-bot이 작성했습니다
lidge-jun commentedon Sep 17, 2026
Fixed on
devby #4875 (ee28833160), released in 2.58.0.After an incomplete tool-call stream the conversation is reminted, the thread override is set, and the stale checkpoint is invalidated — with a bounded counter, because an unbounded remint on a model that fails every turn is worse than the original symptom. The current send is not retried and isolated turns are excluded, which keeps this to preventing new contamination rather than silently replaying work.
fix(cursor,xai): stop grok mid-turn tool-result echoes from sticking
fix(cursor,xai): stop grok mid-turn tool-result echoes from sticking
fix(cursor,xai): stop grok mid-turn tool-result echoes from sticking
fix(cursor,xai): stop grok mid-turn tool-result echoes from sticking
fix(cursor,xai): stop grok mid-turn tool-result echoes from sticking
fix(cursor,xai): stop grok mid-turn tool-result echoes from sticking
fix(cursor,xai): stop grok mid-turn tool-result echoes from sticking
fix(xai): bundle lane B — reasoning-model stop/penalty drops, policy …