-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
Prerequisites
- I will write this issue in English (see our Language Policy)
- I have searched existing issues to avoid duplicates
- I am using the latest version of oh-my-opencode
- I have read the documentation or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
Bug Description
When Sisyphus or its sub-agents (e.g., sisyphus-junior) are interrupted mid-execution (e.g., during session_list / session_read calls), the model sometimes hallucinates a tool call to a non-existent tool upon recovery. OpenCode then throws a dummy_tool error:
▣ Sisyphus · copilotcode-14 · interrupted
⚙ dummy_tool Model tried to call unavailable tool 'invalid'. Available tools: .
This error crashes the agent turn and is not recoverable by the existing session-recovery hook, because detectErrorType() only handles:
tool_result_missingthinking_block_orderthinking_disabled_violationassistant_prefill_unsupported
It does not handle the unavailable tool / NoSuchToolError case.
Root Cause Analysis
-
Model hallucination: When an agent is interrupted (context overflow, timeout, etc.) and the session attempts to resume, the model sometimes generates a tool call to a tool named
'invalid'or other non-existent tool names. -
OpenCode's error handling: OpenCode throws
NoSuchToolError(displayed asdummy_tool) instead of gracefully skipping the invalid tool call and continuing. -
Missing recovery path: The
session-recoveryhook (src/hooks/session-recovery/detect-error-type.ts) doesn't detect this error type, so no recovery is attempted.
Proposed Fix
Add "unavailable_tool" as a new RecoveryErrorType in the session-recovery hook:
In detect-error-type.ts:
export type RecoveryErrorType =
| "tool_result_missing"
| "thinking_block_order"
| "thinking_disabled_violation"
| "assistant_prefill_unsupported"
| "unavailable_tool" // NEW
| null;
export function detectErrorType(error: unknown): RecoveryErrorType {
const message = extractErrorMessage(error);
if (!message) return null;
// NEW: detect unavailable tool errors
if (/tried to call unavailable tool/i.test(message) ||
/dummy_tool/i.test(message)) {
return "unavailable_tool";
}
// ... existing checks
}Recovery strategy: When unavailable_tool is detected, strip the invalid tool call from the message history and retry the turn (similar to how tool_result_missing recovery works).
Steps to Reproduce
- Use a custom OpenAI-compatible provider (e.g., API proxy) that doesn't return
usagedata - Run a complex task with
ultraworkmode — Sisyphus delegates to sub-agents - When context grows large, sub-agents get interrupted
- On resumption, model hallucinates invalid tool calls →
dummy_toolerror - Session is stuck — no recovery possible
Expected Behavior
The session-recovery hook should detect the unavailable tool error and recover by stripping the invalid tool call, allowing the agent to continue working.
Actual Behavior
The error is unrecoverable. The agent shows dummy_tool errors repeatedly until the user manually starts a new session.
Environment
- opencode: 1.1.60
- oh-my-opencode: 3.5.2
- Provider: Custom OpenAI-compatible (via API proxy, no
usagein responses) - OS: macOS (arm64)
- Model: claude-4.6-opus via proxy
Additional Context
This issue is exacerbated when:
- The provider doesn't return token
usagedata (context window monitoring is blind) - Multiple background agents run concurrently
preemptive_compactionis enabled but can't fully prevent overflow
Related OpenCode issues:
- [FEATURE]: Add local token estimation fallback when API usage is empty anomalyco/opencode#13141 (custom provider missing usage → compaction fails)
- Skill "planning" not found. Available skills: no anomalyco/opencode#11722 (skill/tool not found errors)
Error Logs
⚙ session_list [limit=10]
⚙ session_read [session_id=ses_xxx, include_todos=true, limit=30]
Tool execution aborted
▣ Sisyphus · copilotcode-14 · interrupted
⚙ dummy_tool Model tried to call unavailable tool 'invalid'. Available tools: .
▣ Sisyphus · copilotcode-14 · interrupted
⚙ dummy_tool Model tried to call unavailable tool 'invalid'. Available tools: .
⚙ dummy_tool Model tried to call unavailable tool 'invalid'. Available tools: .