can1357/oh-my-pi · error · ToolError
Internal daemon result ${result.op} is not tool-visible
Error message
Internal daemon result ${result.op} is not tool-visible What it means
toolContent() converts a daemon RPC result into user-visible tool output. The 'ping' and 'shutdown' ops are internal-only (they have no meaningful tool-facing content), so if such a result reaches toolContent the code throws ToolError 'Internal daemon result <op> is not tool-visible' — a programming/invariant error indicating an internal result leaked into the tool path.
Source
Thrown at packages/coding-agent/src/tools/hub/launch.ts:299
for (const condition of daemon.readyPending ?? []) {
if (condition === "log") {
parts.push(ready?.log ? `log pattern /${ready.log}/ never matched` : "the log pattern never matched");
} else {
parts.push(
ready?.port !== undefined
? `port ${ready.port} on ${ready.host ?? "127.0.0.1"} never accepted connections`
: "the port never accepted connections",
);
}
}
return parts;
}
function toolContent(result: DaemonRpcResult, params: LaunchParams): string {
switch (result.op) {
case "ping":
case "shutdown":
throw new ToolError(`Internal daemon result ${result.op} is not tool-visible`);
case "start": {
const daemon = result.daemon;
const lines = [`${daemon.state === "failed" ? "Failed to launch" : "Started"} ${daemonLabel(daemon)}`];
if (daemon.state === "failed" && daemon.exitReason) lines.push(`Reason: ${daemon.exitReason}`);
if (daemon.readyMatch) lines.push(`Ready log matched: ${daemon.readyMatch}`);
if (result.readyTimedOut) {
const pending = readyPendingSummary(daemon, params.ready);
const cause = pending.length > 0 ? `: ${pending.join("; ")}` : "";
lines.push(
`NOT ready — readiness timed out after ${params.ready?.timeout ?? 30}s${cause}. The process is still running (state: ${daemon.state}); follow its logs or stop it.`,
);
} else if (params.ready && daemon.readyAt === undefined && TERMINAL_STATES[daemon.state]) {
lines.push("Process exited before readiness was observed.");
}
return lines.join("\n");
}
case "list":
return result.daemons.lengthView on GitHub (pinned to 9690622007)
Solutions
- Don't invoke the launch tool with op 'ping' or 'shutdown' — they are internal daemon-management ops, not tool operations.
- Update operationFor/executeLaunch so internal ops are filtered before toolContent renders them.
- Extend toolContent's switch if a new internal op legitimately needs tool-visible output.
Defensive patterns
Strategy: try-catch
Validate before calling
const TOOL_VISIBLE_OPS = new Set(["start", "stop", "send", "log", "list", "status"]);
if (!TOOL_VISIBLE_OPS.has(params.op)) throw new Error(`op ${params.op} is not a tool-visible launch operation`); Try / catch
try {
const content = launchTool.run(launchParams);
} catch (err) {
if (err instanceof ToolError && err.message.includes("is not tool-visible")) {
// internal-only op (ping/shutdown) reached the tool path — fix routing, don't expose to users
} else throw err;
} Prevention
- Never expose internal ops (ping/shutdown) through the launch tool's public op parameter.
- Extend toolContent whenever new DaemonRpcResult ops are added.
- Add a unit test asserting every op produced by operationFor is handled by toolContent.
When it happens
Trigger: executeLaunch dispatches an operation whose DaemonRpcResult op is 'ping' or 'shutdown' and then attempts to render it as tool content — e.g. an internal keepalive/shutdown result is mistakenly returned by the launch execution path instead of being handled internally.
Common situations: Routing table regression where the shutdown op was exposed as a user-selectable launch op; future refactors adding ops to operationFor without updating toolContent's switch; custom builds of the hub plumbing returning raw RPC results.
Related errors
- snapcompact shape was not resolved before rendering.
- Unsupported language '{value}'. Supported: {}
- Unable to infer language from file extension: {}. Specify `l
- Invalid pattern: {err}
- Overlapping replacements detected; refine pattern to avoid a
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ee90e6f5dd247983.
Report an issue: GitHub.