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
bug: message pipeline has no final empty-content guard, causing ValidationException on Bedrock and hard failures on other providers #23260
The message() pipeline in packages/opencode/src/provider/transform.ts applies a sequential series of transformation passes but has no final validation step. Multiple passes can each leave messages with content: [] or content: "", which providers reject with hard errors that permanently break the active session.
Expected Behavior
No message with empty content should ever reach a provider API.
Actual Behavior
Three transformation passes can each produce empty-content messages with no downstream guard:
Pass
Location
Produces
Pass 1 (Anthropic/Bedrock text filter)
transform.ts:55-73
Guarded locally, but only for two providers
Pass 3 (Anthropic tool reorder flatMap)
transform.ts:115-126
content: [] if the non-tool split half was all-empty text parts
Pass 5 (interleaved reasoning filter)
transform.ts:178-211
content: [] when the assistant message contained only reasoning parts
unsupportedParts()
transform.ts:267-303
content: [] if all parts were unsupported modality
On Bedrock this produces:
ValidationException: messages: text content blocks must be non-empty
This error permanently breaks the session.
Steps to Reproduce
Use a Bedrock model with interleaved reasoning (e.g. amazon-bedrock/zai.glm-4.7)
Send a message that triggers the reasoning filter, producing an assistant message where all content is reasoning parts
The reasoning filter strips all reasoning parts, leaving content: []
Bedrock rejects the next request with ValidationException
Provider: Amazon Bedrock (also affects other providers)
Model: Any model with interleaved reasoning capability, or any Anthropic model on Bedrock
Additional Context
The root cause is architectural: each transformation pass has its own (or no) local guard, and passes added later never see the guards from earlier passes. A single O(n) filter at the end of message() would catch all current and future cases.
The issue itself references these as "related reports", but they appear to describe the same underlying problem. If this issue is intended as a root-cause analysis or umbrella fix rather than a new report, please clarify that distinction in the issue body so maintainers can triage accordingly.
This is an umbrella root-cause issue, not a duplicate report. The referenced issues (#15715, #16332, #17705, #22364) are all symptoms of the same architectural gap: the message() pipeline has no final empty-content validation step, so any transformation pass that produces content: [] or content: "" silently passes through to the provider.
Each of those issues was filed against a specific provider or scenario. This issue identifies the common cause across all of them and tracks PR #23259, which adds a single guard at the end of the pipeline that fixes all current and future cases in one place.
Also reproduces with DeepSeek provider. Adding reproduction details:
Error:
400 Bad Request: messages.55: all messages must have non-empty content
Reproduction:
Configure OpenCode with a DeepSeek provider (e.g., deepseek-chat)
Build up a conversation context with 50+ messages (system prompt + multi-turn tool use + many user/assistant exchanges)
The DeepSeek API rejects with messages.N: all messages must have non-empty content (observed at N=47 and N=55 on different runs)
Environment:
OpenCode version: 1.17.9 (CLI v0.3.28)
Provider: DeepSeek (deepseek-chat)
Platform: macOS (darwin)
Trigger condition: A long-running agent task where context grows to 50+ messages (including a 7800+ char comment with markdown tables). The error occurs consistently once the message count exceeds ~47.
Note: Unlike Bedrock which gives ValidationException, DeepSeek returns a 400 with a specific message index — which is actually more useful for debugging since it pinpoints exactly which message in the array is empty.
This confirms the same root cause (no final empty-content guard in the message pipeline) affects at least three providers: Bedrock, Anthropic, and DeepSeek. The fix proposed in the issue description — a single O(n) filter at the end of message() — would fix all of them.
Activity
github-actions commentedon Apr 18, 2026
This issue might be a duplicate of (or closely related to) existing open issues. Please check:
The issue itself references these as "related reports", but they appear to describe the same underlying problem. If this issue is intended as a root-cause analysis or umbrella fix rather than a new report, please clarify that distinction in the issue body so maintainers can triage accordingly.
jpvelasco commentedon Apr 18, 2026
This is an umbrella root-cause issue, not a duplicate report. The referenced issues (#15715, #16332, #17705, #22364) are all symptoms of the same architectural gap: the
message()pipeline has no final empty-content validation step, so any transformation pass that producescontent: []orcontent: ""silently passes through to the provider.Each of those issues was filed against a specific provider or scenario. This issue identifies the common cause across all of them and tracks PR #23259, which adds a single guard at the end of the pipeline that fixes all current and future cases in one place.
Oxygen56 commentedon Jun 24, 2026
Also reproduces with DeepSeek provider. Adding reproduction details:
Error:
Reproduction:
deepseek-chat)messages.N: all messages must have non-empty content(observed at N=47 and N=55 on different runs)Environment:
Trigger condition: A long-running agent task where context grows to 50+ messages (including a 7800+ char comment with markdown tables). The error occurs consistently once the message count exceeds ~47.
Note: Unlike Bedrock which gives
ValidationException, DeepSeek returns a 400 with a specific message index — which is actually more useful for debugging since it pinpoints exactly which message in the array is empty.This confirms the same root cause (no final empty-content guard in the message pipeline) affects at least three providers: Bedrock, Anthropic, and DeepSeek. The fix proposed in the issue description — a single O(n) filter at the end of
message()— would fix all of them.fix: add final empty-content guard in message() pipeline
test: add empty-content guard tests for message() pipeline
github-actions commentedon Aug 24, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.