40.2 "Explain errors as JSON" for debuggability

Overview and links for this section of the guide.

Why Structured Errors

When something goes wrong, you need machine-parseable error information. String messages aren't enough for automated handling.

Error Schema

const ErrorResponseSchema = z.object({
  success: z.literal(false),
  error: z.object({
    code: z.enum([
      'INVALID_INPUT',
      'AMBIGUOUS_QUERY',
      'INSUFFICIENT_CONTEXT',
      'RATE_LIMITED',
      'INTERNAL_ERROR'
    ]),
    message: z.string(),
    details: z.object({
      field: z.string().optional(),
      expected: z.string().optional(),
      received: z.string().optional(),
      suggestion: z.string().optional()
    }).optional(),
    retryable: z.boolean()
  })
});

// Example error response
{
  "success": false,
  "error": {
    "code": "AMBIGUOUS_QUERY",
    "message": "Multiple columns match 'sales'",
    "details": {
      "suggestion": "Specify: sales_jan, sales_feb, or sales_total"
    },
    "retryable": true
  }
}

Implementation

const SYSTEM_PROMPT = `
When you cannot complete the request, output an error:
{
  "success": false,
  "error": {
    "code": "[ERROR_CODE]",
    "message": "[Human-readable explanation]",
    "details": { ... },
    "retryable": true/false
  }
}

Error codes:
- INVALID_INPUT: User provided bad data
- AMBIGUOUS_QUERY: Multiple interpretations possible
- INSUFFICIENT_CONTEXT: Need more information
`;

function handleResponse(response: any) {
  if (response.success === false) {
    if (response.error.retryable) {
      return promptForClarification(response.error);
    }
    throw new NonRetryableError(response.error.code);
  }
  return response;
}

Where to go next