Error codes

FrontMCP reports problems in two ways. Protocol errors are JSON-RPC error responses with a numeric code: the request itself couldn't be handled. Tool errors are normal results with isError: true: the request was fine, but the tool couldn't do what was asked. Models can read tool errors and try again. Error classes lists the class behind each code, and which ones keep their message in production.

Tool errors

A tool error arrives as a result like this:

{
  "content": [{ "type": "text", "text": "There's no ticket T-9." }],
  "isError": true,
  "_meta": { "errorId": "err_4418a34f3368d9dc", "code": "PUBLIC_ERROR" }
}
_meta.codeCauseFix
INVALID_INPUTThe arguments didn't match inputSchema. execute() didn't run. The text lists each problem.Check the field paths in the message. If a model keeps getting it wrong, describe the field better.
PUBLIC_ERRORThe tool failed with a PublicMcpError, through this.fail() or throw. A PublicMcpError with a code of its own sends that code instead.Intended: the message is for the model.
SERVER_ERRORThe tool called this.fail(new Error(...)) with a plain Error. In production the text is "Internal FrontMCP error" and an error ID.Use PublicMcpError if the message is meant for the model.
INTERNAL_ERRORThe tool failed with an InternalMcpError through this.fail(). An InternalMcpError with a code of its own sends that code. In production the text is "Internal FrontMCP error" and an error ID.Intended, if the message is only for your logs.
TOOL_EXECUTION_ERRORexecute() threw an error that isn't public, like a plain Error or an InternalMcpError. In development the text is prefixed Tool "…" execution failed: and ends with the stack; in production it's "Internal FrontMCP error" and an error ID.Find the error ID in the server's log, next to the original message and stack. Use PublicMcpError for errors the model should read.
INVALID_OUTPUTThe result didn't match the tool's outputSchema, or held NaN or Infinity. An agent's answer that doesn't match its outputSchema fails the same way (since 1.8.7; 1.8.5 and 1.8.6 reported TOOL_EXECUTION_ERROR). In development the text names the first field that didn't match; in production it's "Output validation failed. Please contact support."Fix the result, or the schema if the result is right. See Shaping Tool Results.
FLOW_EXITED_WITHOUT_OUTPUTexecute() returned undefined.Return a value, even { ok: true }.
TOOL_NOT_FOUNDNo tool has that name, the tool has visibility: "internal", or CodeCall takes it out of tools/list (since 1.9). The text is Tool "…" not found.Check the name in tools/list.
AUTHORITY_DENIEDThe caller doesn't pass the tool's authorities rule. execute() didn't run.Sign in as a caller the rule allows, or change the rule.
ENTRY_UNAVAILABLEThe tool's availableWhen doesn't match the environment the server runs in.Run the server where the tool is meant to be available, or change availableWhen.
RATE_LIMIT_EXCEEDED, CONCURRENCY_LIMIT, QUEUE_TIMEOUT, EXECUTION_TIMEOUTA tool's rateLimit, concurrency or timeout, or a throttle default, stopped the call. The message says when to retry, or which limit.Intended. See Guard options.
APPROVAL_REQUIRED, APPROVAL_OPERATION_FAILED, APPROVAL_SCOPE_NOT_ALLOWED, CHALLENGE_VALIDATION_FAILEDThe Approval plugin refused a call that needs the user's approval (APPROVAL_REQUIRED, whose text is the tool's approvalMessage), or a grant it can't make. They are public errors, so the client reads the message in production too.Grant the approval, or change the grant the tool makes.
REMEMBER_SCOPE_NOT_ALLOWEDA memory tool was called with a scope outside the plugin's tools.allowedScopes, the default scope included. The message names the scope and the allowed ones.Pass an allowed scope, or add it to allowedScopes.
FEATURE_FLAG_DISABLEDThe tool is disabled by a feature flag. The text names the tool and the flag.Turn the flag on for the caller, or call a different tool.
REMEMBER_IDENTITY_REQUIREDA Remember scope needs a caller to keep values apart, and the caller is anonymous (session and user scope).Sign the caller in, or use global scope.
AGENT_CALL_DEPTH_EXCEEDEDAn agent called another, which called another, past swarm.maxCallDepth (3 by default). The text lists the agents running. New in 1.9.Give a chain of agents a way to end before the limit: see Agents That Call Agents.
JOB_NOT_AUTHORIZEDexecute_job or execute_workflow was called with a name that doesn't exist, or that the caller may not run.Check the name with list_jobs. See @Job.

Protocol errors

CodeMeaningFix
-32001Unauthorized. A tool needs a credential from one of its authProviders that the user hasn't connected, and data.authUrl says where to connect it (Progressive auth). Also: a resource or prompt that failed with UnauthorizedError, or a request refused by throttle.ipFilter (with HTTP 403).Send the user to authUrl, or mark the provider required: false. For ipFilter, see Guard options.
-32003Forbidden. A resource or prompt refused by an authorities rule, or that failed with a public error whose statusCode is 403.Sign in as a caller who's allowed.
-32020Header mismatch MCP 2026-07-28. A mirrored header (Mcp-Method, Mcp-Name, MCP-Protocol-Version) disagrees with the request body.Send headers that match the body.
-32021Missing client capability MCP 2026-07-28. The request needs a capability the client didn't declare in _meta.Declare the capability in io.modelcontextprotocol/clientCapabilities.
-32022Unsupported protocol version. The error lists the supported and requested versions.Use a version the server supports. FrontMCP serves every revision from 2024-11-05 to 2026-07-28.
-32029Rate limited. The server's throttle.global limit refused the request, with HTTP 429 and a Retry-After header. The message says how many seconds to wait.Wait that long. See Guard options.
-32601Method not found. Under 2026-07-28 this includes removed methods such as initialize, ping and logging/setLevel.Use the 2026-07-28 equivalents, such as server/discover.
-32602Invalid params, including a resource or prompt that doesn't exist (a missing resource was -32002 before 2026-07-28), a missing prompt argument, a call to a task-only tool from a client without the tasks extension, and a public error from a resource or prompt, such as a PublicMcpError, whose code is in data.code.Check the method's parameters and the resource URI, or read the message.
-32603Internal error: a resource or prompt failed with an error that isn't public, or with a public error whose statusCode is 500 or more. For errors that aren't public, production's message is "Internal FrontMCP error" and an error ID.Find the error ID in the server's log. Fail with a PublicMcpError if the message is for the client. See this.fail.

Error classes shows how an error's statusCode picks its code.

HTTP status codes

Under 2026-07-28, GET and DELETE on the MCP endpoint return 405: every request is a POST, and there's no session to close. Tool errors, including every tool limit, arrive with 200. throttle.global answers with 429 and throttle.ipFilter with 403, before the request reaches a tool (see Guard options), and the Node HTTP server answers 413 for a body over http.bodyLimit.