Skip to content

fix: don't insert relocated system text before tool_result blocks - #257

Draft
darknessest wants to merge 1 commit into
griffinmartin:mainfrom
darknessest:fix-relocated-system-text-before-tool-results
Draft

fix: don't insert relocated system text before tool_result blocks#257
darknessest wants to merge 1 commit into
griffinmartin:mainfrom
darknessest:fix-relocated-system-text-before-tool-results

Conversation

@darknessest

Copy link
Copy Markdown

While chasing recurring 400s from Anthropic during opencode's session compaction, I traced it back to the system-prompt relocation in transformBody.

What happens: when the request's first user message carries tool_result blocks (which is the norm for compaction requests — their history often starts with an assistant tool_use turn), the relocated system text gets unshifted in front of the results. Anthropic wants tool_results to be the leading blocks of the message that follows a tool_use, so it rejects the whole request:

messages.2: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_...

Regular chat requests never hit this (their first user message is plain text), which makes it look like a mysterious compaction-only failure. It also keeps re-failing on every auto-compaction retry until the tail boundary happens to shift, so sessions get stuck in an error loop near the context limit.

Repro/verification: captured a failing compaction request from a live session, replayed it against the API — 400 with the exact error above. Moved the injected text block after the tool_results, replayed again — 200. That one-block reorder is this patch.

Fix: insert the relocated text after any leading tool_result blocks instead of always at index 0. Added a regression test.

Marking as draft since I only exercised the compaction path against the real API — happy to adjust if you'd rather relocate into a different message entirely.

Anthropic requires tool_result blocks to be the leading content of the
message that follows a tool_use. Unshifting the relocated system prompt
text in front of them makes the API reject the request with
"tool_use ids were found without tool_result blocks immediately after".
Compaction requests are the common victim: their first user message is
the tool_result carrier for a leading assistant tool_use turn.
@carson2222

Copy link
Copy Markdown

Independent repro, same root cause.

opencode 1.18.11 auto-compaction anchored its tail on an assistant tool_use turn, so the first role:user message of the compaction request was a pure tool_result carrier. transformBody's system-text relocation then unshifted a text block in front of the results and Anthropic rejected the request:

messages.2: `tool_use` ids were found without `tool_result` blocks immediately after: call_..., call_..., ...

(ids can be OpenAI-style when earlier turns in the session ran on a non-Anthropic model — the transform is id-agnostic, so it reproduces either way.)

Confirmed the failure loops on every compaction retry until the tail boundary shifts. Applied this branch locally (merged onto 2.1.5), transforms suite passes 43/43 incl. the new regression test, and compaction works again. Would be good to get this out of draft.

@carson2222

Copy link
Copy Markdown

@griffinmartin LGTM, confirming this fixes a real failure
I've been running this patch on top of main (2.1.6) for a while and it resolves the annoying compaction 400s

One small nit, optional chaining on the block lookup :213
firstUser.content[insertAt]?.type === "tool_result"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants