mastra-ai/mastra · error · MastraError
MCP_CLIENT_TOOL_EXECUTION_FAILED
MCP_CLIENT_TOOL_EXECUTION_FAILED
Error message
${errorText} What it means
Thrown when an MCP tool executes successfully at the transport level but the tool's result carries isError: true, and the client is configured with onToolError: 'throw'. The library extracts the human-readable error text from the result content and wraps it in a MastraError (id MCP_CLIENT_TOOL_EXECUTION_FAILED, category THIRD_PARTY) so the failure surfaces through spans, stream chunks, scorers, and persisted message parts. The error text comes from the MCP server itself, not from Mastra.
Source
Thrown at packages/mcp/src/client/client.ts:1485
arguments: input,
...(combinedMeta ? { _meta: combinedMeta } : {}),
},
{
timeout: this.timeout,
signal: context?.abortSignal,
},
);
// Per the MCP spec, tool *execution* failures are reported in-band:
// the server returns a normal CallToolResult with `isError: true` and
// the failure details in `content`. Map that onto Mastra's failed-tool-call
// path (unless the consumer opted into the legacy `'return'` behaviour) so
// tool spans, stream chunks, scorers, and persisted message parts reflect the
// failure, and the model sees the error text so it can self-correct.
if (res.isError && this.onToolError === 'throw') {
const errorText = extractToolErrorText(res.content);
this.log('debug', `Tool reported an error: ${tool.name}`, { error: errorText });
throw new MastraError({
id: 'MCP_CLIENT_TOOL_EXECUTION_FAILED',
domain: ErrorDomain.MCP,
category: ErrorCategory.THIRD_PARTY,
text: errorText,
details: { toolName: tool.name, serverName: this.name },
});
}
this.log('debug', `Tool executed successfully: ${tool.name}`);
if (res.structuredContent !== undefined) {
return attachMcpCallToolContent(
res.structuredContent,
res.content,
res._meta ? this.stampServerIdInMeta(res._meta) : undefined,
);
}
View on GitHub (pinned to 75dd419e61)
Solutions
- Read the errorText in the message/details — it is the server's own failure reason; fix the arguments or server-side condition it reports.
- If you want the model to see the error text and self-correct instead of the call throwing, configure the client with onToolError: 'propagate' (or the legacy 'return') so the error is returned as a tool result rather than thrown.
- Add argument validation on your side before invoking the tool (check required params, formats, ranges against the tool's input schema).
- Check MCP server logs for the corresponding execution to find the underlying failure.
Example fix
// before
const client = new MastraMCPClient({ name: 'my-server', server, onToolError: 'throw' });
const res = await tool.execute({ query: 'drop table' }); // throws MCP_CLIENT_TOOL_EXECUTION_FAILED
// after: let the model see and recover from the error text
const client = new MastraMCPClient({ name: 'my-server', server, onToolError: 'propagate' });
const res = await tool.execute({ query: 'select * from users' }); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate inputs against the tool's schema before executing
import { z } from 'zod';
tool.inputSchema.parse(args); // throws early on bad client-side arguments Type guard
function isToolExecutionError(e: unknown): e is MastraError {
return e instanceof MastraError && e.id === 'MCP_CLIENT_TOOL_EXECUTION_FAILED';
} Try / catch
try {
return await tool.execute(args);
} catch (e) {
if (isToolExecutionError(e)) {
logger.warn({ tool: e.details.toolName, server: e.details.serverName }, e.message); // e.message is the server's error text
return { isError: true, content: [{ type: 'text', text: e.message }] }; // feed back to the model
}
throw e;
} Prevention
- Prefer onToolError: 'propagate' (or 'return') when you want the model to self-correct instead of throwing.
- Validate tool arguments against the input schema before every call.
- Read the server's error text in the message — it names the actual server-side cause.
- Monitor server logs for the corresponding execution to catch recurring failures.
When it happens
Trigger: Calling an MCP tool via InternalMastraMCPClient (e.g. await tool.execute(...)) when the remote tool returns { isError: true, content: [...] } while the client was constructed with onToolError: 'throw' (the strict behavior).
Common situations: The tool's internal logic failed on the server (invalid arguments the schema allowed, missing upstream resource, permission denied on the server side, rate limit); server-side bugs; large payloads the server rejects.
Related errors
- MCP_CLIENT_GET_PROMPT_FAILED
- A2A stream error - ${JSON.stringify(parsed.error)}
- Factory transitions require an authenticated bound agent too
- MASTRA_MEMORY_GET_EMBEDDING_DIMENSION_FAILED
- No arguments provided
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/bf4b87b4407a4275.
Report an issue: GitHub.