You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
With long running copilot sessions I've been hitting an issue: unexpected tool_use_id found in tool_result #1005
✗ Model call failed: messages.0.content.1: unexpected tool_use_id found in tool_result blocks: toolu_vrtx_01SDJuRhCZGEMZ61MCTUXRM7. Each tool_result block must
have a corresponding tool_use block in the previous message. (Request ID: B218:798AF:2DF53B:341624:696A65C1)
Affected version
0.0.384
Steps to reproduce the behavior
I'm not sure, usually this happens if I've had a copilot cli session running for a couple days working on a problem.
I also encountered this when using --resume on a session, and traced it through the codebase.
Root Cause Analysis
The bug is in the K8l function in the Copilot codebase (index.js). This function is called during session.resume and abort events to repair conversation history, but it only handles one direction of orphaned messages.
What K8l Currently Does
functionK8l(t){if(t.length===0)returnt;lete=[];// orphanedToolCallIdsletn=newSet;// seenToolResultIds letr=false;// foundAssistant// Iterates BACKWARDS through messagesfor(leto=t.length-1;o>=0;o--){lets=t[o];if(s.role==="assistant"&&(r=true),s.role==="assistant"&&"tool_calls"ins&&s.tool_calls?.length>0){for(letIofs.tool_calls)n.has(I.id)||e.push(I.id);}else{if(r)break;// ⚠️ STOPS scanning after first assistant messages.role==="tool"&&s.tool_call_id&&n.add(s.tool_call_id);}}if(e.length===0)returnt;// Adds fake "interrupted" results for orphaned tool_callsletl="The execution of this tool, or a previous tool was interrupted.";leta=e.map(o=>({role: "tool",tool_call_id: o,content: l}));return[...t, ...a];}
The Bug
Scenario
Handled?
Orphaned tool_calls (assistant has tool requests but no results)
✅ Adds fake "interrupted" results
Orphaned tool_results (tool results exist but matching tool_call is missing)
❌ Not handled - causes API error
Why This Causes the Error
API Contract: Both Anthropic and OpenAI APIs require strict pairing - every tool_result must have a corresponding tool_use/tool_call in the previous assistant message
Session Interruption: When a session is interrupted mid-tool-execution:
tool.execution_complete events may persist to disk
assistant.message events (containing toolRequests) may be lost (not yet flushed)
On Resume: K8l is called but doesn't filter out orphaned tool_results
Result: Messages containing tool_result without matching tool_use get sent to the API → validation error
Proposed Fix
Extend K8l to also filter out orphaned tool_results:
functionK8l(messages){if(messages.length===0)returnmessages;// Step 1: Collect ALL tool_call IDs from ALL assistant messagesconstallToolCallIds=newSet();for(constmsgofmessages){if(msg.role==="assistant"&&msg.tool_calls){for(consttcofmsg.tool_calls)allToolCallIds.add(tc.id);}}// Step 2: Filter out orphaned tool_results (no matching tool_call)constcleanedMessages=messages.filter(msg=>{if(msg.role==="tool"&&msg.tool_call_id){if(!allToolCallIds.has(msg.tool_call_id)){// Optionally log: Fe.warn(`Removing orphaned tool_result: ${msg.tool_call_id}`);returnfalse;}}returntrue;});// Step 3: Find orphaned tool_calls (calls without results)constseenResultIds=newSet(cleanedMessages.filter(m=>m.role==="tool").map(m=>m.tool_call_id));constorphanedCallIds=[...allToolCallIds].filter(id=>!seenResultIds.has(id));// Step 4: Add fake results for orphaned tool_calls (existing logic)if(orphanedCallIds.length===0)returncleanedMessages;constfakeResults=orphanedCallIds.map(id=>({role: "tool",tool_call_id: id,content: "The execution of this tool, or a previous tool was interrupted."}));return[...cleanedMessages, ...fakeResults];}
How to Locate the Function
Search for the string literal "The execution of this tool, or a previous tool was interrupted." in the codebase.
Analysis performed by tracing: loadSession → $Y.fromEvents → event processing → K8l called on session.resume event
Hi @PureWeen - there was a bug in the CLI where in some cases, background compaction could lead to the conversation history getting into a bad state. This was fixed in version 0.0.384 but sessions started in older versions can still be affected.
If you want to recover your old session, you can do the following:
Resume the session
Run the /session command and open up the events file included in the output
Navigate to the last compaction_completed event, reduce the preCompactionMessagesLength value by 1, and save the file
Close the CLI and resume the session again
I'll close this issue since a fix has been deployed but please let us know if you run into this again in any new sessions.
Activity
JohanVanosmael commentedon Jan 16, 2026
I also encountered this when using
--resumeon a session, and traced it through the codebase.Root Cause Analysis
The bug is in the
K8lfunction in the Copilot codebase (index.js). This function is called duringsession.resumeandabortevents to repair conversation history, but it only handles one direction of orphaned messages.What
K8lCurrently DoesThe Bug
tool_calls(assistant has tool requests but no results)tool_results(tool results exist but matching tool_call is missing)Why This Causes the Error
API Contract: Both Anthropic and OpenAI APIs require strict pairing - every
tool_resultmust have a correspondingtool_use/tool_callin the previous assistant messageSession Interruption: When a session is interrupted mid-tool-execution:
tool.execution_completeevents may persist to diskassistant.messageevents (containingtoolRequests) may be lost (not yet flushed)On Resume:
K8lis called but doesn't filter out orphaned tool_resultsResult: Messages containing
tool_resultwithout matchingtool_useget sent to the API → validation errorProposed Fix
Extend
K8lto also filter out orphaned tool_results:How to Locate the Function
Search for the string literal
"The execution of this tool, or a previous tool was interrupted."in the codebase.Analysis performed by tracing:
loadSession→$Y.fromEvents→ event processing →K8lcalled onsession.resumeeventssfdre38 commentedon Jan 17, 2026
dereklegenzoff commentedon Jan 18, 2026
Hi @PureWeen - there was a bug in the CLI where in some cases, background compaction could lead to the conversation history getting into a bad state. This was fixed in version 0.0.384 but sessions started in older versions can still be affected.
If you want to recover your old session, you can do the following:
/sessioncommand and open up the events file included in the outputcompaction_completedevent, reduce thepreCompactionMessagesLengthvalue by 1, and save the fileI'll close this issue since a fix has been deployed but please let us know if you run into this again in any new sessions.