Structured Error Response Design

Tools

Definition

The practice of returning structured, actionable error information from tools rather than generic error strings. Well-designed error responses include: error type, what went wrong, what Claude should try next. Prevents Claude from retrying the same failing approach repeatedly.

Example Usage

Return {error: 'PERMISSION_DENIED', resource: '/etc/passwd', suggestion: 'Request a path within /tmp instead'} rather than 'Error: access denied'.

Why It Matters for the CCA-F Exam

Exam questions on error response design typically describe a scenario where an agent loops or produces wrong output after a tool failure, then ask what change to the tool's error response would fix it. Know that `is_error: true` plus a structured message is the correct API-level mechanism, and that actionable suggestions in the error body enable Claude to self-correct without human intervention.

In Depth

Structured error response design is the practice of returning machine-readable, actionable error information from tools rather than opaque strings or silent failures. It is a Domain 2 design topic because how your tools communicate failure directly shapes how reliably Claude navigates problems in an agentic loop.

When Claude calls a tool and receives a generic error like "Error: failed", it has little basis for deciding what to do next. It may retry with identical parameters, it may escalate to the user unnecessarily, or — worst case — it may hallucinate a plausible-sounding result because the tool appeared to succeed. Structured errors short-circuit all three failure modes.

A well-formed error response includes at minimum:

  • Error type — a machine-readable code like "PERMISSION_DENIED", "NOT_FOUND", "RATE_LIMITED", or "INVALID_PARAM".
  • What went wrong — a human-readable description scoped to the specific call, not a generic stack trace.
  • What to try next — a concrete suggestion Claude can act on: "Request a path within /tmp", "Retry after 60 seconds", "Use the search_products tool to find a valid product ID first".

The is_error: true flag on tool_result signals to Claude that the call failed, not that it returned empty data. Without it, Claude may interpret an error string as legitimate output and continue reasoning incorrectly. Always pair is_error: true with a useful content string.

Error design also integrates with validation loops: if an error tells Claude exactly what parameter was wrong and what format is expected, Claude can self-correct in the next turn without human intervention. This is the difference between a loop that converges in two turns and one that spins indefinitely.

Keep errors predictable. If your tool sometimes returns a JSON error object and sometimes throws an uncaught exception, Claude's behavior will be unpredictable. Document the error format in the tool description so Claude knows what to expect and how to parse it. See Structured Error Response Design and Error Recovery & Retry Patterns for architectural patterns.

How It Compares

Error response qualityExampleClaude's likely behavior
Generic string"Error: failed"Uncertain retry, possible hallucination
Typed but no suggestion{error: "NOT_FOUND"}Stops or asks user — limited self-correction
Typed + description{error: "NOT_FOUND", message: "Product ID 99 not found"}May try a different ID, may escalate
Typed + description + suggestion{error: "NOT_FOUND", message: "Product 99 not found", suggestion: "Use search_products to find a valid ID"}High likelihood of correct self-correction
is_error omitted, error in contentError text returned with is_error defaulting to falseClaude may treat error string as valid data

Frequently Asked Questions

Should I always return a JSON object for errors, or is a plain string acceptable?

A plain string with `is_error: true` is acceptable and often sufficient for simple errors. A structured JSON object (serialized to a string in `content`) is preferable when you have multiple error codes, when the error carries data Claude needs to act on (like a retry-after duration), or when downstream code needs to parse the error type.

What is the difference between `is_error: true` and returning a success result that contains error text?

`is_error: true` tells Claude at the API level that the tool call failed, giving it a clear semantic signal. Returning error text as a success result (`is_error` false or omitted) can cause Claude to interpret the error message as factual output — for example, treating `"Record not found"` as the record's value. Always use `is_error: true` for genuine failures.

Does including a `suggestion` field guarantee Claude will follow it?

No — Claude reasons over the suggestion and may choose a different recovery path based on broader context. But a concrete, accurate suggestion dramatically increases the probability of correct recovery in the next turn and eliminates the most common failure modes (identical retry, spurious escalation). Think of it as giving Claude the information it needs, not as programming it.