opencode icon indicating copy to clipboard operation
opencode copied to clipboard

Empty message content causes Anthropic API errors during compaction

Open Melodeiro opened this issue 3 weeks ago • 2 comments

Description

During compaction, Anthropic API returns:

messages.9: all messages must have non-empty content except for the optional final assistant message

Root Cause Analysis

After investigating the storage data, found the following message structure in the problematic session:

[0] user     | parts: text
[1] assistant | parts: step-start, tool (completed), step-finish  ← NO TEXT
[2] assistant | parts: step-start, tool (completed), step-finish  ← NO TEXT, consecutive
[3] assistant | parts: step-start, tool (completed), step-finish  ← NO TEXT, consecutive
[4] assistant | parts: step-start, text, step-finish
[5] user     | parts: text
...

Key observations:

  1. Messages [1], [2], [3] are consecutive assistant messages with only tool calls (no text)
  2. step-finish part type is not handled in toModelMessage() (lines 480-537)
  3. The filter on line 541 passes these messages because they have tool-* parts (not just step-start)

The Conversion Pipeline

In packages/opencode/src/session/message-v2.ts:

// Line 541
return convertToModelMessages(result.filter((msg) => msg.parts.some((part) => part.type !== "step-start")))

The convertToModelMessages from AI SDK (ai package) then converts UIMessage[] to ModelMessage[].

Hypothesis: When convertToModelMessages processes consecutive assistant messages with tool calls, it may:

  1. Create synthetic user messages for tool results
  2. These synthetic messages might end up empty in certain edge cases
  3. Or the merging logic creates an empty content array

Affected Code

  • packages/opencode/src/session/message-v2.ts:421-542toModelMessage() function
  • Called from packages/opencode/src/session/compaction.ts

Questions

  1. How does convertToModelMessages handle consecutive assistant messages with tool calls?
  2. Should toModelMessage() merge consecutive assistant messages before passing to convertToModelMessages?
  3. Should there be validation after convertToModelMessages to filter out empty messages?

Reproduction

Session with multiple consecutive assistant messages containing only tool calls (no text parts) followed by compaction trigger.

OpenCode version

1.0.209

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

Xubuntu 22.04

Terminal

ghostty

Melodeiro avatar Dec 30 '25 14:12 Melodeiro

This issue might be a duplicate of existing issues. Please check:

  • #5028: Call Missing content in messages: text content blocks must be non-empty - similar API error about empty message content during message processing
  • #5187: Ollama: User message content arrives as empty array - model cannot see user input - related issue with empty message content in the message pipeline
  • #6068: [BUG]: Auto compaction not triggering reliably with Anthropic models - compaction-related issue with Anthropic API errors

Feel free to ignore if none of these address your specific case.

github-actions[bot] avatar Dec 30 '25 14:12 github-actions[bot]

Can u share a session u got this error w/?

Simply run this:

opencode export > session.json

And send the session

rekram1-node avatar Dec 30 '25 15:12 rekram1-node

+1 I've had to stop using Opus in opencode because of this :(

zitongcharliedeng avatar Dec 31 '25 16:12 zitongcharliedeng

Can u plz send a session :)

rekram1-node avatar Dec 31 '25 17:12 rekram1-node

Can't really since I was working on something personal, but I was around 137 messages in, latest Opencode version as of today, using the oh-my-opencode plugin, when it suddenly just came up with this error pattern, no matter how many undos I tried. I reinstalled and on a new session it is somehow is fixed for now? :shrug:

zitongcharliedeng avatar Dec 31 '25 21:12 zitongcharliedeng

This should be fixed

rekram1-node avatar Jan 06 '26 16:01 rekram1-node