Problem
When the AI model makes structural mistakes (e.g., passing cwd as an object instead of a string, nesting tool calls inside parameters, or emitting XML tool markup alongside native tool calls), Zoo Code currently:
- Shows raw error messages that the AI cannot parse or learn from
- Repeats the same mistake until
consecutiveMistakeLimit is reached
- Displays an interactive "Continue" button that freezes the workflow until the user manually intervenes
This affects all models but is especially prevalent with MiMo models, where ~80% of diagnostics show CWD_OBJECT_MISUSE as the dominant failure mode.
Related Issues
This middleware addresses or provides infrastructure for the following existing bug reports:
Directly Covered by This Middleware
| Issue |
Title |
Pattern Coverage |
How Middleware Helps |
| #752 |
Shell Integration Warning when using MiMo |
SHELL_INTEGRATION/001 |
When shell integration fails, middleware returns a guided message telling the AI to use non-shell tools instead of looping. Prevents the 10+ consecutive failure spiral described in the issue. |
| #704 |
Shell Integration Error persists after long sessions |
SHELL_INTEGRATION/001 |
Same as #752. The dead terminal reuse infinite loop is mitigated by the MODEL_STUCK_LOOP circuit breaker — after 3 failures, the AI is directed to change strategy entirely. |
| #800 |
Terminal cannot capture results, dialog stuck |
MODEL_STUCK_LOOP |
The circuit breaker prevents the "stuck at Running" state by resetting consecutiveMistakeCount and directing the AI to try a different approach after 3 occurrences. |
| #794 |
Errors Produced by Open Weight Models + Solutions |
All patterns |
This issue's community patches (Guide G1/G2/G3, XML fallback P1) are the direct inspiration for this middleware. Our middleware formalizes the "guide the AI" philosophy into official, testable infrastructure with 9+1 categorized patterns instead of minified extension.js patches. |
| #547 |
DeepSeek 5 structural tool-calling defects |
PARAM_MISSING, XML_NATIVE_DUAL_PROTOCOL, CONTEXT_OVERFLOW |
Defect 1 (Missing Required Parameters) → PARAM_MISSING/001 pattern. Defect 4 (XML Tag Fallback) → XML_NATIVE_DUAL_PROTOCOL pattern strips XML and guides to native tool_use. Defect 3 (reasoning_content loss) → CONTEXT_OVERFLOW/001 auto-recovery. |
| #709 |
Tool call serialization failure - XML output |
XML_NATIVE_DUAL_PROTOCOL |
When mimo-v2.5-pro outputs XML tags alongside native calls, middleware strips the XML from visible text and merges a protocol guide into the native tool's result. The AI sees "Use native tool_use only" and self-corrects. |
| #707 |
Chat output truncation at 8KB - XML tool calls as raw text |
XML_NATIVE_DUAL_PROTOCOL |
Same pattern as #709. Middleware detects XML markers in text blocks and strips them before rendering. Combined with the 10,000-char text-length guard to prevent over-stripping on very long responses. |
| #695 |
Streaming tool-call argument deltas silently dropped |
PARAM_MISSING/001 |
When streaming data loss causes missing parameters, the PARAM_MISSING pattern returns a guided message with the tool's required parameters and correct usage example, instead of a cryptic "missing nativeArgs" error. |
| #459 |
Claude model proxy errors/spinning |
MODEL_STUCK_LOOP |
When the model enters an error loop, the circuit breaker at occurrence 3 resets consecutiveMistakeCount and issues a [MODEL_STUCK_LOOP] directive. The interactive "Continue" button is suppressed — the AI self-corrects. |
| #458 |
Requests keep spinning |
MODEL_STUCK_LOOP |
Same circuit breaker mechanism. Prevents indefinite spinning by directing the AI to change strategy. |
Indirectly Related (Middleware Provides Partial Coverage)
| Issue |
Title |
Relationship |
| #648 |
Un-controllable Token Exceed with MCP results |
CONTEXT_OVERFLOW/001 pattern provides auto-recovery guidance when context window is exceeded. Does not prevent the overflow itself, but guides the AI to compress or continue from summary. |
| #427 |
Shell-integration polling refactor |
SHELL_INTEGRATION/001 handles the error gracefully when shell integration fails, regardless of the underlying polling mechanism. Complementary fixes. |
| #471 |
Infinite JSON tool loop on Ollama |
MODEL_STUCK_LOOP circuit breaker prevents infinite loops. Does not fix the Ollama tool-calling detection issue itself. |
Not Covered (Outside Middleware Scope)
| Issue |
Reason |
| #257 |
Chat stuck on "API Request" — UI state management issue, not tool error |
| #877 |
Ollama model refresh stuck — settings panel UI issue |
| #937 |
Message processing order at terminal finish — task lifecycle issue |
| #856 |
Task Tree Abstraction — architecture enhancement |
| #464 |
Universal AI Clipboard — new feature proposal |
Originally, you had to click the 'Proceed Anyway' button to proceed in this state, but I changed it to a format that guides the AI to perform the correct task, as shown below.
Solution: Error Interception Middleware
A new middleware layer that intercepts, classifies, and transforms tool errors into actionable guidance messages, enabling the AI to self-correct without user intervention.
Architecture
Tool Error → ErrorClassifier → ErrorPattern DB (9+1 categories)
↓
MessageTransformer → Versioned JSON guidance
↓
TaskErrorState (WeakMap) → Circuit Breaker
↓
Exactly one guided tool_result → AI self-corrects
New Modules
| Module |
Purpose |
errorPatterns.ts |
Pattern DB with 9+1 error categories and variant entries |
ErrorClassifier.ts |
Deterministic error classifier (priority-ordered pattern matching) |
MessageTransformer.ts |
Versioned JSON guidance serializer (WHAT/WHY/NEXT format) |
TaskErrorState.ts |
Task-scoped persistent state via WeakMap (occurrence tracking, circuit breaker) |
StructuralValidator.ts |
CWD object detection + nested parameter overflow detection |
ToolErrorInterceptor.ts |
Interceptor facade (transformError, circuit status) |
Error Patterns Covered
| # |
Category |
Pattern ID |
Trigger |
Behavior |
Related Issues |
| 1 |
DUPLICATE_CALL |
EI/DUPLICATE_CALL/001 |
Repeated identical tool call |
Block + guide |
— |
| 2 |
PARAM_MISSING |
EI/PARAM_MISSING/001 |
Required parameter missing |
Block + guide with example |
#695, #547 Defect 1 |
| 3 |
PARAM_TYPE_MISMATCH |
EI/PARAM_TYPE_MISMATCH/001 |
Generic type mismatch |
Block + guide |
— |
| 4 |
PARAM_TYPE_MISMATCH |
EI/PARAM_TYPE_MISMATCH/002 |
CWD passed as object |
Block + guide "cwd must be a string" |
— |
| 5 |
PARAM_TYPE_MISMATCH |
EI/PARAM_TYPE_MISMATCH/003 |
Nested tool invocation in param |
Block + guide "issue separate calls" |
— |
| 6 |
FILE_NOT_FOUND |
EI/FILE_NOT_FOUND/001 |
File/directory not found |
Guide to use list_files |
— |
| 7 |
SHELL_INTEGRATION |
EI/SHELL_INTEGRATION/001 |
Shell integration failure |
Guide to use non-shell tools |
#752, #704, #427 |
| 8 |
MCP_TOOL_MISSING |
EI/MCP_TOOL_MISSING/001 |
MCP tool/server not found |
Guide to select from list |
— |
| 9 |
INVALID_TOOL_PROTOCOL |
EI/INVALID_TOOL_PROTOCOL/001 |
XML tool calls in text |
Strip XML + guide |
#709, #707 |
| 10 |
INVALID_TOOL_PROTOCOL |
EI/INVALID_TOOL_PROTOCOL/002 |
XML + native dual protocol |
Strip XML + merge protocol guide |
#709, #707, #547 Defect 4 |
| 11 |
CONTEXT_OVERFLOW |
EI/CONTEXT_OVERFLOW/001 |
Context window exceeded |
Auto-recovery guide |
#648, #547 Defect 3 |
| 12 |
MODEL_STUCK_LOOP |
(circuit breaker) |
Same error 3x |
Strategy change directive, no user prompt |
#800, #459, #458, #752, #704 |
Circuit Breaker (MODEL_STUCK_LOOP)
| Occurrence |
Behavior |
| 1 |
Guided correction (variant-specific message) |
| 2 |
Strengthened guidance ("Re-read the tool schema now") |
| 3 |
Circuit opens — [MODEL_STUCK_LOOP] directive, consecutiveMistakeCount reset, no user prompt |
Design Philosophy (from #794)
"We have two options: (1) Suppress error messages and let the AI self-correct, (2) When the AI exhibits a bad habit that causes errors, guide it toward the correct approach. We prefer option 2."
This middleware implements option 2 as official, testable infrastructure. Each error produces a WHAT/WHY/NEXT guidance payload that tells the AI:
- WHAT went wrong (specific, not generic)
- WHY it happened (root cause, not symptom)
- NEXT what to do (actionable steps, not vague advice)
Before vs After
| Scenario |
Before |
After |
AI sends cwd: {command: "..."} |
Terminal error → raw message → AI repeats → user must click Continue |
Preflight blocks → guided tool_result with "cwd must be a string" → AI self-corrects |
| AI emits XML + native tool call |
Confusing partial execution → user must intervene (#709, #707) |
XML stripped, native executes, protocol guide merged |
| AI nests parallel params in one call |
Cryptic error → user must Continue |
Preflight detects nested signature → guided "issue separate calls" |
| Same mistake 3x |
consecutiveMistakeLimit → interactive prompt → user must click (#800, #459) |
Circuit breaker → [MODEL_STUCK_LOOP] → AI changes strategy |
| Shell integration failure |
Raw error → AI retries same terminal → infinite loop (#752, #704) |
SHELL_INTEGRATION/001 guide → AI uses non-shell tools |
Test Coverage
- 113 tests across 7 test files, all passing
- StructuralValidator: CWD detection, nested param detection, allow-list, cycle detection
- TaskErrorState: Occurrence tracking, circuit open/close, fingerprint, reset, WeakMap isolation
- presentAssistantMessage: 7 integration tests (CWD blocked, circuit at occurrence 3, nested overflow, XML+native, etc.)
- model-stuck-loop: 10 tests (accumulation, threshold, suppression, per-Task isolation)
Files Changed
| File |
Type |
Description |
src/core/tools/error-interception/errorPatterns.ts |
Modified |
3 variant entries (CWD, NESTED, XML_DUAL) |
src/core/tools/error-interception/TaskErrorState.ts |
New |
Task-scoped persistent state (WeakMap) |
src/core/tools/error-interception/StructuralValidator.ts |
New |
CWD + nested param detection |
src/core/assistant-message/presentAssistantMessage.ts |
Modified |
Structural preflight + XML detection + FP-1 fix (classify errors by message content) |
src/core/task/Task.ts |
Modified |
MODEL_STUCK_LOOP circuit breaker |
src/core/tools/error-interception/index.ts |
Modified |
Stable exports |
| Test files (4 new) |
New |
113 tests total |
Commits
fc38100a6 — feat: complete gap-fix for 4 uncovered error patterns (+1460/-2)
291f4594b — fix: resolve false positive PARAM_TYPE_MISMATCH on validateToolUse failures (+13/-1)
Replaces closed #999 (could not add labels due to repository permissions).
Problem
When the AI model makes structural mistakes (e.g., passing
cwdas an object instead of a string, nesting tool calls inside parameters, or emitting XML tool markup alongside native tool calls), Zoo Code currently:consecutiveMistakeLimitis reachedThis affects all models but is especially prevalent with MiMo models, where ~80% of diagnostics show
CWD_OBJECT_MISUSEas the dominant failure mode.Related Issues
This middleware addresses or provides infrastructure for the following existing bug reports:
Directly Covered by This Middleware
SHELL_INTEGRATION/001SHELL_INTEGRATION/001MODEL_STUCK_LOOPcircuit breaker — after 3 failures, the AI is directed to change strategy entirely.MODEL_STUCK_LOOPconsecutiveMistakeCountand directing the AI to try a different approach after 3 occurrences.extension.jspatches.PARAM_MISSING,XML_NATIVE_DUAL_PROTOCOL,CONTEXT_OVERFLOWPARAM_MISSING/001pattern. Defect 4 (XML Tag Fallback) →XML_NATIVE_DUAL_PROTOCOLpattern strips XML and guides to native tool_use. Defect 3 (reasoning_content loss) →CONTEXT_OVERFLOW/001auto-recovery.XML_NATIVE_DUAL_PROTOCOLXML_NATIVE_DUAL_PROTOCOLPARAM_MISSING/001PARAM_MISSINGpattern returns a guided message with the tool's required parameters and correct usage example, instead of a cryptic "missing nativeArgs" error.MODEL_STUCK_LOOPconsecutiveMistakeCountand issues a[MODEL_STUCK_LOOP]directive. The interactive "Continue" button is suppressed — the AI self-corrects.MODEL_STUCK_LOOPIndirectly Related (Middleware Provides Partial Coverage)
CONTEXT_OVERFLOW/001pattern provides auto-recovery guidance when context window is exceeded. Does not prevent the overflow itself, but guides the AI to compress or continue from summary.SHELL_INTEGRATION/001handles the error gracefully when shell integration fails, regardless of the underlying polling mechanism. Complementary fixes.MODEL_STUCK_LOOPcircuit breaker prevents infinite loops. Does not fix the Ollama tool-calling detection issue itself.Not Covered (Outside Middleware Scope)
Originally, you had to click the 'Proceed Anyway' button to proceed in this state, but I changed it to a format that guides the AI to perform the correct task, as shown below.
Solution: Error Interception Middleware
A new middleware layer that intercepts, classifies, and transforms tool errors into actionable guidance messages, enabling the AI to self-correct without user intervention.
Architecture
New Modules
errorPatterns.tsErrorClassifier.tsMessageTransformer.tsTaskErrorState.tsStructuralValidator.tsToolErrorInterceptor.tsError Patterns Covered
Circuit Breaker (MODEL_STUCK_LOOP)
[MODEL_STUCK_LOOP]directive,consecutiveMistakeCountreset, no user promptDesign Philosophy (from #794)
This middleware implements option 2 as official, testable infrastructure. Each error produces a WHAT/WHY/NEXT guidance payload that tells the AI:
Before vs After
cwd: {command: "..."}tool_resultwith "cwd must be a string" → AI self-correctsconsecutiveMistakeLimit→ interactive prompt → user must click (#800, #459)[MODEL_STUCK_LOOP]→ AI changes strategySHELL_INTEGRATION/001guide → AI uses non-shell toolsTest Coverage
Files Changed
src/core/tools/error-interception/errorPatterns.tssrc/core/tools/error-interception/TaskErrorState.tssrc/core/tools/error-interception/StructuralValidator.tssrc/core/assistant-message/presentAssistantMessage.tssrc/core/task/Task.tssrc/core/tools/error-interception/index.tsCommits
fc38100a6— feat: complete gap-fix for 4 uncovered error patterns (+1460/-2)291f4594b— fix: resolve false positive PARAM_TYPE_MISMATCH on validateToolUse failures (+13/-1)