Bug Report
Error
undefined: The model returned the following errors:
messages.3.content.6: `thinking` or `redacted_thinking` blocks in the latest assistant message
cannot be modified. These blocks must remain as they were in the original response.
Root Cause
In packages/opencode/src/session/processor.ts, the reasoning-end handler trims the reasoning text before storing it in SQLite:
case "reasoning-end":
if (value.id in reasoningMap) {
const part = reasoningMap[value.id]
part.text = part.text.trimEnd() // ← BUG: trims text permanently
// ...
if (value.providerMetadata) part.metadata = value.providerMetadata // signature is for ORIGINAL text
await Session.updatePart(part)
}
The Amazon Bedrock API computes the signature cryptographically over the exact original bytes of the reasoning text (including trailing whitespace). When opencode calls trimEnd():
- Stored text:
"Let me think..." (trimmed)
- Stored signature: computed over
"Let me think...\n\n" (original)
On the next request, Bedrock receives text ≠ signature → ValidationException: "cannot be modified".
Data Flow
Bedrock response: reasoning.text = "thinking...\n\n", signature = "sig123"
↓
processor.ts reasoning-end: part.text = "thinking..." (trimEnd applied)
↓
SQLite: { text: "thinking...", metadata: { bedrock: { signature: "sig123" } } }
↓
Next request: text = "thinking...", signature = "sig123"
↓
Bedrock validates: sig123 was for "thinking...\n\n" ≠ "thinking..." → ERROR ❌
Fix
In packages/opencode/src/session/processor.ts, remove trimEnd() from the reasoning-end case:
case "reasoning-end":
if (value.id in reasoningMap) {
const part = reasoningMap[value.id]
// REMOVED: part.text = part.text.trimEnd()
// Reasoning text must be preserved byte-for-byte — the API-provided signature
// validates the exact content. Trimming invalidates the signature and causes
// "thinking blocks cannot be modified" on the next Bedrock request.
part.time = { ...part.time, end: Date.now() }
if (value.providerMetadata) part.metadata = value.providerMetadata
await Session.updatePart(part)
delete reasoningMap[value.id]
}
Related Bug in @ai-sdk/amazon-bedrock
A secondary bug exists in packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.ts where trimIfLast() is applied to reasoning blocks that have a signature:
// BUGGY (line 298):
text: trimIfLast(isLastBlock, isLastMessage, isLastContentPart, part.text),
signature: reasoningMetadata.signature,
// FIX: never trim when signature is present
text: reasoningMetadata.signature != null
? part.text
: trimIfLast(isLastBlock, isLastMessage, isLastContentPart, part.text),
signature: reasoningMetadata.signature,
This should be reported separately to vercel/ai.
Reproduction
- Configure OpenCode with Claude Opus 4 via Amazon Bedrock (extended thinking enabled)
- Have a multi-turn conversation where extended thinking is used
- Error appears on the turn after extended thinking was used (typically turn 2-3)
Environment
- OpenCode: v1.2.27
- Provider:
amazon-bedrock
- Model:
global.anthropic.claude-opus-4-6-v1 (variant: max)
- Confirmed in oh-my-opencode logs:
ValidationException on converse-stream
Bug Report
Error
Root Cause
In
packages/opencode/src/session/processor.ts, thereasoning-endhandler trims the reasoning text before storing it in SQLite:The Amazon Bedrock API computes the
signaturecryptographically over the exact original bytes of the reasoning text (including trailing whitespace). When opencode callstrimEnd():"Let me think..."(trimmed)"Let me think...\n\n"(original)On the next request, Bedrock receives text ≠ signature → ValidationException: "cannot be modified".
Data Flow
Fix
In
packages/opencode/src/session/processor.ts, removetrimEnd()from thereasoning-endcase:Related Bug in
@ai-sdk/amazon-bedrockA secondary bug exists in
packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.tswheretrimIfLast()is applied to reasoning blocks that have a signature:This should be reported separately to vercel/ai.
Reproduction
Environment
amazon-bedrockglobal.anthropic.claude-opus-4-6-v1(variant: max)ValidationExceptiononconverse-stream