Skip to content

Openapi Error Envelope

FieldValue
TypeSkill Resource
Source~/.copilot/skills/backend/templates/openapi-error-envelope.yaml
DescriptionNot specified

Source Content

# Canonical RFC 9457 (application/problem+json) Problem Details schema block.
#
# Vendors the error-handling conventions already documented in this skill —
# see references/api-design.md § "Error envelope: RFC 9457 Problem Details"
# and references/openapi.md. Field names, status codes, and problem-type
# strings below match those references exactly; do not invent new ones.
#
# Usage: paste the `components` block into api/openapi.yaml, then reference
# `#/components/schemas/ProblemDetails` from each operation's error responses.
components:
schemas:
ProblemDetails:
type: object
description: >-
RFC 9457 Problem Details for HTTP APIs. Every error response uses
this shape — never a bare string, never an ad-hoc error object.
required:
- title
- status
properties:
type:
type: string
format: uri
description: A URI identifying the problem type. Stable and dereferenceable.
example: "https://api.example.com/errors#payment-failed"
title:
type: string
description: Short, human-readable summary of the problem type.
example: "Payment Processing Failed"
status:
type: integer
minimum: 400
maximum: 599
description: The HTTP status code for this occurrence of the problem.
example: 402
detail:
type: string
description: Human-readable explanation specific to this occurrence.
example: "Card declined: insufficient funds"
instance:
type: string
format: uri
description: URI identifying the specific occurrence (usually the request path).
example: "/invoices/inv-123"
responses:
BadRequest:
description: Validation failed — malformed JSON or a missing required field.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
example:
type: "https://api.example.com/errors#bad-request"
title: "Bad Request"
status: 400
detail: "field 'amount' is required"
instance: "/invoices"
Unauthorized:
description: Authentication missing or invalid.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
example:
type: "https://api.example.com/errors#unauthorized"
title: "Unauthorized"
status: 401
detail: "missing or invalid bearer token"
instance: "/invoices"
Forbidden:
description: Authenticated but not authorized for this resource.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
example:
type: "https://api.example.com/errors#forbidden"
title: "Forbidden"
status: 403
detail: "caller lacks the invoices:write scope"
instance: "/invoices/inv-123"
NotFound:
description: Resource does not exist.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
example:
type: "https://api.example.com/errors#not-found"
title: "Not Found"
status: 404
detail: "invoice inv-123 does not exist"
instance: "/invoices/inv-123"
Conflict:
description: State conflict — duplicate resource or failed precondition.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
example:
type: "https://api.example.com/errors#conflict"
title: "Conflict"
status: 409
detail: "invoice inv-123 is already finalized"
instance: "/invoices/inv-123"
ValidationError:
description: Semantic validation failed (e.g., a past date for a future deadline).
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
example:
type: "https://api.example.com/errors#validation-error"
title: "Validation Error"
status: 422
detail: "due_date must be in the future"
instance: "/invoices"
RateLimitExceeded:
description: Rate limit hit. Response includes a Retry-After header.
headers:
Retry-After:
schema:
type: integer
description: Seconds to wait before retrying.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
example:
type: "https://api.example.com/errors#rate-limit-exceeded"
title: "Rate Limit Exceeded"
status: 429
detail: "more than 100 requests in 60s"
instance: "/invoices"
InternalError:
description: >-
Server error. Never echo internal error text (stack traces, driver
errors, SQL) to the client — map to this generic shape instead.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
example:
type: "https://api.example.com/errors#internal-error"
title: "Internal Server Error"
status: 500
detail: "an unexpected error occurred"
instance: "/invoices"
# Reference from an operation like this:
#
# paths:
# /invoices/{id}:
# get:
# operationId: getInvoice
# responses:
# "200":
# description: Invoice found.
# "404":
# $ref: "#/components/responses/NotFound"
# "500":
# $ref: "#/components/responses/InternalError"