Bugfix: Why are raw Claude API errors (tool_use/tool_result mismatch...
Documentation for Sessions
🐛 Bugfix: Why are raw Claude API errors (tool_use/tool_result mismatch...
Date: 2026-03-21
Time: 17:37:27 UTC
Session: gspace1-250.10
Agent: backend
Confidence: 97%
Status: ✅ Documented
📋 Decision Context
Question:
Why are raw Claude API errors (tool_use/tool_result mismatch, 400 status) being sent directly to WhatsApp users?
Task: S250: Fix raw API errors reaching WhatsApp users
🎯 Decision Made
Chosen:
Three-layer fix: (1) Agent loop no longer appends raw LLM errors to finalOutput — logs full error, returns graceful user message instead. (2) routeTaskResponse strips any [ERROR:...] patterns from output before sending to any channel — defense in depth. (3) Pre-send validation in agent loop scans all messages for orphaned tool_use IDs and injects synthetic tool_result blocks before calling Claude API — prevents the 400 error from occurring in the first place.
Options Considered:
- Only fix the error display (hide from users but don't prevent the 400)
- Only fix the tool_use pairing (prevent 400 but still expose other errors)
- Three-layer fix: prevent 400 + hide errors + graceful fallback (chosen)
💭 Reasoning
Root cause chain: (1) Agent loop catches SmartRouter failure at line 377, appends raw error to finalOutput: [ERROR: All LLM providers failed — ${err.message}]. (2) err.message contains full Claude API error detail including request IDs, tool IDs, JSON error bodies. (3) Channel processing treats this as successful output (task status = completed), routes it through routeTaskResponse. (4) sanitizeOutput only strips credentials/env vars, not API errors. (5) Raw error reaches WhatsApp user. The tool_use/tool_result mismatch itself likely occurs when context windowing or early breaks leave orphaned tool_use blocks. The S185 backfill (line 901) covers normal cases but not edge cases where messages are manipulated between iterations. The pre-send validation is the definitive fix — it runs right before every LLM call and ensures pairing is always correct.
📁 Files Involved
APIs/backend-vitto-api/src/app/engine/agent-loop.service.tsAPIs/backend-vitto-api/src/app/engine/channel-processing.service.ts
🔗 Related
- Decision ID:
dev_1774114647116_3gda3wj - Session: 250
- Workspace: gspace1
Auto-generated by MCP Smart Consolidation