{"slug": "your-error-messages-are-talking-to-machines-now", "title": "Your Error Messages Are Talking to Machines Now", "summary": "The Model Context Protocol (MCP) specification now explicitly requires tool-call failures to be returned inside a normal successful response with the `isError` field set to true, rather than as a low-level protocol error, because AI agents act on error text as their sole input. The article notes that RFC 9457, \"Problem Details for HTTP APIs,\" has defined structured machine-readable errors since 2023 as an update to RFC 7807, with fields for `type`, `title`, `status`, and `detail`, yet many APIs still ship vague messages like `{\"error\": \"bad request\"}`. The shift matters because a vague error can stall an entire pipeline or trigger a blind retry, while a convincingly worded fake error can smuggle in a hidden instruction.", "body_md": "[← writing](https://aien.me)\n\n# Your Error Messages Are Talking to Machines Now\n\nAI agents don't read your error messages the way people do, they act on them. As MCP and autonomous coding agents take over, a vague error can stall an entire pipeline, and a convincingly worded fake one can smuggle in a hidden instruction.\n\nSomewhere in the middle of 2026, something quietly flipped: for a growing share of API calls, CLI commands, and tool invocations, the thing reading your error message on the other end isn't a person anymore. It's a model, working through a task, deciding what to do next based entirely on the text your program just sent back. That's not a guess about where things are heading. It's written directly into the protocol a huge share of this traffic now runs on.\n\n## MCP Basically Says the Quiet Part Out Loud\n\nThe Model Context Protocol, the thing letting AI agents call tools, hit APIs, and run commands on your behalf, has a specific field built for exactly this: `isError`. When a tool call fails, the spec is explicit that the failure should come back inside a normal, successful response, with `isError` set to true, rather than as a low-level protocol error. The reasoning given is blunt: bury the failure at the protocol level instead of surfacing it in the result, and the model never even sees that anything went wrong, let alone gets a chance to fix it ([MCP specification](https://modelcontextprotocol.io/specification/2025-06-18/server/tools?ref=aien.me)).\n\nThat's an unusually direct thing for a technical spec to spell out, but it names exactly what's happening underneath it: an error message is no longer a diagnostic afterthought written for whoever debugs the logs later. It's an input straight into another agent's next decision, and the spec was shaped around that on purpose.\n\n## Nobody Used to Read Your Errors This Closely\n\nFor most of software history, an error message had a small, forgiving audience. A developer squinting at a stack trace mid-debug. A user who saw \"Something went wrong,\" sighed, and refreshed the page. Vague was annoying, but survivable, humans are good at filling gaps with context, patience, or a quick search.\n\nAn agent working through an MCP tool call, or debugging its own generated code, doesn't get that luxury. It has the text you sent back, and nothing else. It can't read tone or guess intent. It can't tell whether \"something went wrong\" means a missing API key, a timeout, or a malformed payload. If the message doesn't say, the agent is left making a blind retry, or worse, confidently doing the wrong thing next, at whatever speed it's running.\n\nA quick honesty point here, because it's worth resisting the urge to oversell this: machine-readable errors don't make failure disappear, and treating every error as something an agent should silently patch around is its own kind of risk. Some failures genuinely need a human to look at them, and hiding that behind an automatic retry loop just delays the reckoning. The point isn't \"remove the human.\" It's making sure whichever reader shows up next, human or agent, actually has enough to act on.\n\n## The Blueprint Already Existed. It Just Wasn't Urgent Before.\n\nNone of this required inventing something new. [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457.html?ref=aien.me), \"Problem Details for HTTP APIs,\" has quietly existed since 2023 as an update to the older RFC 7807, and it already defines what a structured, machine-readable error should look like: a stable `type`, a short `title`, the `status`, and a `detail` string with the specifics of that particular failure. It was built, explicitly, so that machines consuming an API wouldn't have to parse free-form English to work out what happened.\n\nFor years, plenty of APIs ignored it anyway and shipped `{\"error\": \"bad request\"}`, because the cost of being vague was mostly one mildly annoyed developer. That cost has changed shape. The reader on the other end might now be an autonomous agent burning through retries, tokens, and, depending on the task, real actions in the world, all because one field it needed wasn't there.\n\n## A Fake Error Can Attack the Reader Too\n\nIf an agent treats error text as something to act on, then so does an agent reading someone else's error text, including text an attacker planted there on purpose. This isn't a hypothetical extension of the argument, it's an entire documented class of attack. Security researchers call it indirect, or tool-mediated, prompt injection: instead of typing a malicious prompt at the model directly, an attacker hides one inside content the agent is only supposed to read as data, a webpage, a document, or a tool result, and waits for the agent to treat it as an instruction instead ([CrowdStrike](https://www.crowdstrike.com/en-us/blog/indirect-prompt-injection-attacks-hidden-ai-risks/?ref=aien.me)). A benchmark built specifically to measure this, InjecAgent, found tool-integrated agents falling for it a large share of the time, even on strong models ([InjecAgent](https://github.com/uiuc-kang-lab/InjecAgent?ref=aien.me)).\n\nAn error message is one of the cleanest injection points available, because it arrives with an unusual amount of built-in trust: it comes back from a tool the agent already decided to call, on the exact channel the protocol tells it to read for recovery guidance. OWASP's write-up on MCP tool poisoning names the underlying gap directly: a server's tools get reviewed once, when the agent first connects, but nothing re-checks what actually comes back at runtime, so a compromised or malicious server can return a \"failure\" whose real payload is a hidden instruction rather than a diagnosis ([OWASP](https://owasp.org/www-community/attacks/MCP_Tool_Poisoning?ref=aien.me)). A convincingly worded fake error, complete with a plausible code and a helpful-sounding suggested fix, is an effective delivery mechanism precisely because it looks like the same boring, trustworthy infrastructure text this whole post has been arguing you should write.\n\nThe honest caveat: better wording doesn't fix this on its own. This is a system-level trust problem, not a phrasing problem, and it doesn't go away no matter how carefully you write your own messages. What it means in practice is that error text, yours and everyone else's, needs to be handled the way any other untrusted tool output is handled: content for the agent to reason about, not instructions it's allowed to execute, with the actual decisions and permissions sitting somewhere that text can't reach into.\n\n## What This Actually Demands From You Now\n\nNone of it is exotic. It's the same advice good engineers have been giving for years, just with a sharper reason to finally act on it:\n\n- **State what was expected and what showed up.** \"Invalid input\" tells nobody anything. \"Expected an ISO 8601 date for`start_date` , received`'next tuesday'` \" tells a human and a model exactly what to change.\n- **Give it a stable, structured shape.** a`type` or error code, not just a sentence  so an agent, or a downstream service, can branch on it without regex-matching prose that might get reworded next release.\n- **Say what to do next, if there's an obvious next step.** A concrete suggestion turns a dead end into a retry the agent can actually execute.\n- **Don't get cute.** A joke or a vague apology gives a model nothing to parse, and doesn't do much for a stressed human either.\n- **Keep it consistent across your whole surface.** An agent that learns your error shape once should be able to rely on it everywhere, not relearn it endpoint by endpoint.\n\n## Why This Actually Matters\n\nThis isn't really a story about writing nicer error messages, on its own that wouldn't be worth a post. It's about who's actually consuming your software now. A meaningful share of the traffic hitting your code today isn't a person clicking through a UI, it's an agent working through a task list, and the only channel it has back to you, or forward into whatever it does next, is whatever text you decided to send the moment something broke.\n\nThe tools for doing this well have existed for years. What changed is the cost of skipping them. A vague error used to waste a few minutes of a developer's patience. Today it can quietly stall an entire automated pipeline, and nobody notices until the task just doesn't happen.", "url": "https://wpnews.pro/news/your-error-messages-are-talking-to-machines-now", "canonical_source": "https://aien.me/your-error-messages-are-talking-to-machines-now/", "published_at": "2026-09-13 08:20:23+00:00", "updated_at": "2026-09-13 08:26:25.830047+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-safety"], "entities": ["Model Context Protocol", "MCP", "RFC 9457", "RFC 7807"], "alternates": {"html": "https://wpnews.pro/news/your-error-messages-are-talking-to-machines-now", "markdown": "https://wpnews.pro/news/your-error-messages-are-talking-to-machines-now.md", "text": "https://wpnews.pro/news/your-error-messages-are-talking-to-machines-now.txt", "jsonld": "https://wpnews.pro/news/your-error-messages-are-talking-to-machines-now.jsonld"}}