Skip to content
Back to skills

Problem Details Error Design

ASecurity

Playbook for designing a consistent RFC 9457 Problem Details error model — type URIs, extension members, status code mapping, and a catalog template. Prevents per-endpoint bespoke error shapes.

  • 7 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 23, 2026
ai-agentsgojavaapidocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 23, 2026

npx -y skills add mcorbett51090/RavenClaude --skill problem-details-error-design --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Problem Details Error Design?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Problem Details Error Design
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mcorbett51090-problem-details-error-design/badge)](https://www.skillsdirectory.com/skills/mcorbett51090-problem-details-error-design)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: problem-details-error-design
description: "Playbook for designing a consistent RFC 9457 Problem Details error model — type URIs, extension members, status code mapping, and a catalog template. Prevents per-endpoint bespoke error shapes."
---

# Problem Details Error Design (RFC 9457)

## When to Use This Skill

Apply at design time — before a single error response is coded — and when auditing an existing API for inconsistent error shapes.

## 1. Problem Details Shape

```json
{
  "type": "https://api.example.com/problems/order-not-found",
  "title": "Order Not Found",
  "status": 404,
  "detail": "Order ord_9f3c1a was not found or has been deleted.",
  "instance": "/orders/ord_9f3c1a"
}
```

| Field | Required | Notes |
|---|---|---|
| `type` | Yes | A stable URI that never changes; resolves to human-readable docs |
| `title` | Yes | Short, human-readable, consistent for the same `type` |
| `status` | Yes | Must match the HTTP response status code |
| `detail` | No | Instance-specific, safe to show end-users; never a stack trace |
| `instance` | No | URI identifying the specific occurrence — good for log correlation |

**Media type:** `Content-Type: application/problem+json` (never `application/json` for errors).

## 2. Type URI Design Rules

1. Use a stable base URL your team controls: `https://api.example.com/problems/`
2. Use kebab-case slugs that name the condition, not the HTTP status: `order-not-found`, `insufficient-inventory`, `rate-limit-exceeded`
3. Never reuse a URI for two different conditions
4. The URI should resolve to documentation — consumers bookmark them

```
https://api.example.com/problems/order-not-found        ← correct
https://api.example.com/problems/404                    ← wrong (status not condition)
https://api.example.com/problems/OrderNotFoundException ← wrong (Java exception name leaked)
```

## 3. Status Code to Problem Type Mapping

| HTTP Status | Typical `type` slug | Notes |
|---|---|---|
| 400 | `invalid-input` | Validation failure; add `errors` extension (see below) |
| 401 | `unauthenticated` | Missing/expired/invalid token |
| 403 | `forbidden` | Valid token, insufficient permission (BOLA/BFLA) |
| 404 | `{resource}-not-found` | Include the resource type in the slug |
| 409 | `{resource}-conflict` | Duplicate, state conflict |
| 422 | `unprocessable-entity` | Semantically invalid (e.g. future date in past-only field) |
| 429 | `rate-limit-exceeded` | Add `Retry-After` header and extension members |
| 500 | `internal-error` | Never leak detail or stack trace |

## 4. Extension Members for Validation Errors

```json
{
  "type": "https://api.example.com/problems/invalid-input",
  "title": "Invalid Input",
  "status": 400,
  "detail": "The request body failed validation.",
  "errors": [
    { "pointer": "/quantity", "detail": "Must be a positive integer." },
    { "pointer": "/shippingAddress/zip", "detail": "Invalid ZIP code format." }
  ]
}
```

`pointer` follows JSON Pointer (RFC 6901). This avoids per-field response envelopes.

## 5. Problem Catalog Template

Maintain a `problems.yaml` alongside the OpenAPI spec:

| Type slug | Status | Title | When emitted | Extension members |
|---|---|---|---|---|
| `order-not-found` | 404 | Order Not Found | Order ID absent from store | — |
| `invalid-input` | 400 | Invalid Input | Schema/constraint violation | `errors[]` |
| `insufficient-inventory` | 409 | Insufficient Inventory | Stock check fails | `available`, `requested` |
| `rate-limit-exceeded` | 429 | Rate Limit Exceeded | Quota burst | `retryAfterSeconds` |

## 6. OpenAPI Schema Declaration

```yaml
components:
  schemas:
    Problem:
      type: object
      required: [type, title, status]
      properties:
        type:
          type: string
          format: uri
          example: "https://api.example.com/problems/order-not-found"
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
        instance:
          type: string
          format: uri
      additionalProperties: true
```

## Pitfalls

- Returning a 200 with an `{"error": "..."}` body — consumers cannot branch on status code
- Leaking exception class names, stack traces, or internal IDs in `detail`
- Using a different `title` for the same `type` URI across responses — title must be stable per type
- Defining the error schema inline per operation instead of `$ref`-ing a shared component
- Using `application/json` instead of `application/problem+json` — clients lose the semantic signal

## See Also

- [`../../agents/api-implementation-engineer.md`](../../agents/api-implementation-engineer.md) — HTTP semantics and status code mapping
- [`../../agents/api-design-architect.md`](../../agents/api-design-architect.md) — contract-first design and OpenAPI authoring
- [`../../CLAUDE.md`](../../CLAUDE.md) — house opinion: one error model across all endpoints

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…