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
Empty text parts in assistant message history cause 422 on strict providers #31046
When a model responds with only tool calls, processor.ts opens a text block (text-start) that closes immediately (text-end) with no delta in between. This leaves a TextPart with text: "" persisted in the DB.
On the next turn, toModelMessagesEffect replays this as { type: "text", text: "" } in the assistant message. Providers that strictly validate message content reject it:
Azure AI (and other strict OpenAI-compatible endpoints) — returns HTTP 422
AWS Bedrock — same Anthropic surface, same rejection
Why the AI SDK's built-in filter doesn't catch this
convertToLanguageModelMessage() in the AI SDK does filter empty text parts, but skips the filter when providerOptions != null. On Anthropic-protocol paths, text-start events can carry non-null providerMetadata, which gets stored on the TextPart. This triggers the exception and lets the empty part survive to the wire even after convertToModelMessages runs.
Root cause
The user message loop in toModelMessagesEffect already guards against this:
fix(opencode): filter empty assistant content for @ai-sdk/openai-compatible
Same symptom; fixes it at the transform.ts layer for a specific provider allowlist. This issue is about the upstream source in message-v2.ts, which affects all providers. Complementary, not conflicting.
This is fixed in #45839 — the text branch now skips empty text parts during conversion (the Anthropic signed-reasoning space substitution still runs first, so signed separators are unaffected). Verified with regression tests plus a replay of a real bricked session's history.
Hit the same failure family (Kimi K3 via an OpenAI-compatible gateway). While waiting for the core fix (#45839), this plugin works around it at send time — it hooks experimental.chat.messages.transform and drops empty text parts plus reasoning-only step segments from replayed history so no empty assistant message reaches the wire: https://github.com/impptg/opencode-fix-empty-assistant-messages
Note it only prevents new requests from failing; a session whose stored history is already poisoned needs a one-time DB cleanup (~/.local/share/opencode/opencode.db) or the upstream fix, which heals old sessions at conversion time. Plugin is removable once #45839 ships.
Activity
luiscga commentedon Jun 26, 2026
@rekram1-node any update on this ?
github-actions commentedon Aug 26, 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.
impptg commentedon Aug 28, 2026
This is fixed in #45839 — the text branch now skips empty text parts during conversion (the Anthropic signed-reasoning space substitution still runs first, so signed separators are unaffected). Verified with regression tests plus a replay of a real bricked session's history.
impptg commentedon Aug 31, 2026
Hit the same failure family (Kimi K3 via an OpenAI-compatible gateway). While waiting for the core fix (#45839), this plugin works around it at send time — it hooks
experimental.chat.messages.transformand drops emptytextparts plus reasoning-only step segments from replayed history so no empty assistant message reaches the wire: https://github.com/impptg/opencode-fix-empty-assistant-messagesNote it only prevents new requests from failing; a session whose stored history is already poisoned needs a one-time DB cleanup (
~/.local/share/opencode/opencode.db) or the upstream fix, which heals old sessions at conversion time. Plugin is removable once #45839 ships.