coleam00/Archon · error
❌ Error: MCP tool failed
Error message
❌ Error: MCP tool failed
What it means
Fallback branch of the same MCP failure path as error 553: when item.error exists but has no usable `message` field, the yielded tool_result output is the static string '❌ Error: MCP tool failed'. This guarantees the agent receives an explicit error result (toolOutcome 'error') instead of a silent success when the MCP server's error payload is malformed or empty.
Source
Thrown at packages/providers/src/codex/provider.ts:744
getLog().debug({ itemId: item.id, status: item.status }, 'file_change_no_changes');
}
break;
}
case 'mcp_tool_call': {
const server = item.server as string | undefined;
const tool = item.tool as string | undefined;
const mcpToolName = getMcpToolName(item);
if ((item.status as string) === 'failed') {
getLog().warn(
{ server, tool, error: item.error, itemId: item.id },
'mcp_tool_call_failed'
);
const mcpError = item.error as { message?: string } | undefined;
const errMsg = mcpError?.message
? `❌ Error: ${mcpError.message}`
: '❌ Error: MCP tool failed';
yield {
type: 'tool_result',
toolName: mcpToolName,
toolOutput: errMsg,
toolCallId: itemId,
toolOutcome: 'error',
};
} else {
let toolOutput = '';
const mcpResult = item.result as { content?: unknown } | undefined;
if (mcpResult?.content) {
if (Array.isArray(mcpResult.content)) {
toolOutput = JSON.stringify(mcpResult.content);
} else {
getLog().warn(
{
itemId: item.id,
server,View on GitHub (pinned to 0773b97458)
Solutions
- Check the 'mcp_tool_call_failed' log entry — the raw item.error is logged there even when no message string existed.
- Update or fix the MCP server to emit a structured error with a `message` field.
- Reproduce the call against the server directly to find why the error payload is empty.
- If the server uses an old MCP SDK, upgrade it so errors serialize with messages.
Example fix
// before (server-side, non-standard error)
throw { code: 123 };
// after
throw new Error('failed to read config file: permission denied'); Defensive patterns
Strategy: type-guard
Validate before calling
// server side: ensure errors always serialize with a message
try {
await runTool(args);
} catch (err) {
throw new Error(err instanceof Error ? err.message : String(err));
} Type guard
function hasMcpErrorMessage(err: unknown): err is { message: string } {
return typeof err === 'object' && err !== null
&& typeof (err as { message?: unknown }).message === 'string'
&& (err as { message: string }).message.length > 0;
} Try / catch
const mcpError = item.error as { message?: string } | undefined;
const errMsg = mcpError && hasMcpErrorMessage(mcpError)
? `Error: ${mcpError.message}`
: 'Error: MCP tool failed'; // fallback keeps the agent informed, log carries raw error Prevention
- Always throw Error instances (not plain objects) in MCP tool implementations.
- Upgrade MCP servers built on old SDKs so errors serialize with messages.
- Include the raw item.error in server logs whenever the fallback string is used.
- Test each tool's failure path, not just its success path.
When it happens
Trigger: An MCP tool call fails but the server's error item has no error object, or the error object lacks a string `message` (e.g. `{code: ...}` only, a non-Error thrown value, or a truncated/binary payload).
Common situations: Custom or third-party MCP servers returning non-standard error shapes; server crashes producing truncated error frames; older MCP SDK versions emitting minimal error objects; a tool that rejects the call without explaining why.
Related errors
- ❌ Error: ${mcpError.message}
- mcp_env_vars_missing
- OpenAI token ${operation} response did not include an id_tok
- MCP config ${fieldPath}.${key} must be a string (got ${descr
- MCP server "${serverName}" must be a JSON object (got ${desc
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/36bf70999220a76d.
Report an issue: GitHub.