Skip to content

fix(opencode): strip trailing assistant messages to prevent prefill 400#51

Merged
ualtinok merged 1 commit into
cortexkit:mainfrom
iceteaSA:fix/opencode-prefill-strip
Jun 1, 2026
Merged

fix(opencode): strip trailing assistant messages to prevent prefill 400#51
ualtinok merged 1 commit into
cortexkit:mainfrom
iceteaSA:fix/opencode-prefill-strip

Conversation

@iceteaSA
Copy link
Copy Markdown
Contributor

@iceteaSA iceteaSA commented Jun 1, 2026

Problem

rewriteRequestBody() never removed trailing assistant-role messages. A resumed or compacted session that ends on an assistant turn (e.g. after a failed tool round, or a session restored mid-response) reached Anthropic with assistant-message prefill. Claude Code OAuth models reject this:

This model does not support assistant message prefill.
The conversation must end with a user message.  (HTTP 400)

This recurs in practice on session resume/compaction and forces the user to manually send another message to recover.

Fix

Add stripTrailingAssistantMessages() and call it right after JSON.parse(body), so trailing assistant messages are popped before billing-header computation and signing. This mirrors the behavior of the built-in @ai-sdk/anthropic provider and the packages/pi conversion path, which already strip trailing assistant messages.

Only messages after the last user message are removed — the active user turn and any assistant message followed by a user message are always preserved. The alternative (no strip) is a hard 400 that returns nothing.

Tests

Adds 5 tests:

  • strips single trailing assistant message
  • strips multiple trailing assistant messages
  • preserves assistant message followed by user message
  • preserves assistant tool_use followed by user tool_result
  • strips trailing assistant after tool_result + assistant

Updates existing fixtures that previously ended on assistant turns to end on user messages. All opencode tests pass (264), typecheck clean, biome clean.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.


Summary by cubic

Strips trailing assistant messages during request rewrite so conversations end with a user message, preventing Anthropic Claude Code OAuth 400 “assistant message prefill” errors. Aligns behavior with @ai-sdk/anthropic and packages/pi.

  • Bug Fixes
    • Added stripTrailingAssistantMessages() and called it in rewriteRequestBody() right after JSON.parse.
    • Only removes assistant messages after the last user message; preserves assistant→user and tool_usetool_result flows.
    • Added 5 tests for strip/preserve scenarios and updated fixtures to end on user messages.

Written for commit ca249f9. Summary will update on new commits.

Review in cubic

rewriteRequestBody() never removed trailing assistant-role messages, so a
resumed or compacted session that ends on an assistant turn (e.g. after a
failed tool round) reached Anthropic with assistant-message prefill. Claude
Code OAuth models reject this with "This model does not support assistant
message prefill. The conversation must end with a user message." (HTTP 400).

Add stripTrailingAssistantMessages() and call it right after JSON.parse so
trailing assistant messages are popped before billing/signing. Mirrors the
behavior of the built-in @ai-sdk/anthropic provider and packages/pi. Adds 5
tests; updates existing fixtures that ended on assistant turns.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

@ualtinok ualtinok merged commit d94ae59 into cortexkit:main Jun 1, 2026
3 of 4 checks passed
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