Error Codes
PEAC Protocol defines 139 error codes across 12 categories. All errors follow the RFC 9457 (Problem Details for HTTP APIs) format, providing machine-readable error responses with stable error codes.
Error format
Every PEAC error response conforms to the RFC 9457 structure:
RFC 9457 Error Response
{
"type": "https://www.peacprotocol.org/errors/E_INVALID_SIGNATURE",
"title": "Invalid Signature",
"status": 400,
"detail": "Receipt signature verification failed",
"instance": "/api/verify",
"peac_error_code": "E_INVALID_SIGNATURE"
}
| Field | Description |
|---|---|
type | Canonical URL for the error type |
title | Human-readable error title |
status | HTTP status code |
detail | Human-readable explanation of the specific error |
instance | URI reference identifying the specific occurrence |
peac_error_code | Stable PEAC error code for programmatic handling |
Categories
| Category | Count | Description |
|---|---|---|
verification | 2 | Signature and key verification |
validation | 16 | Format, claim, and field validation |
infrastructure | 4 | JWKS fetch, rate limiting, circuit breaker |
control | 2 | Policy engine authorization decisions |
identity | 13 | Agent identity attestation |
attribution | 14 | Source attribution and content hashing |
bundle | 15 | Evidence bundle creation and validation |
dispute | 14 | Dispute evidence and resolution |
interaction | 14 | Interaction evidence schema |
workflow | 8 | Workflow DAG and step validation |
verifier | 17 | Verifier-side checks and policy |
ucp | 20 | Universal Commerce Protocol signatures |
Verification errors
| Code | Title | HTTP | Retriable |
|---|---|---|---|
E_INVALID_SIGNATURE | Invalid Signature | 400 | No |
E_KEY_NOT_FOUND | Key Not Found | 400 | No |
Validation errors
| Code | Title | HTTP | Retriable |
|---|---|---|---|
E_INVALID_FORMAT | Invalid Format | 400 | No |
E_EXPIRED | Receipt Expired | 400 | No |
E_NOT_YET_VALID | Not Yet Valid | 400 | Yes |
E_INVALID_ISSUER | Invalid Issuer | 400 | No |
E_INVALID_AUDIENCE | Invalid Audience | 400 | No |
E_INVALID_AMOUNT | Invalid Amount | 400 | No |
E_INVALID_CURRENCY | Invalid Currency | 400 | No |
E_INVALID_RAIL | Invalid Payment Rail | 400 | No |
E_MISSING_REQUIRED_CLAIM | Missing Required Claim | 400 | No |
E_EVIDENCE_NOT_JSON | Evidence Not JSON-Safe | 400 | No |
E_INVALID_SUBJECT | Invalid Subject | 400 | No |
E_INVALID_RECEIPT_ID | Invalid Receipt ID | 400 | No |
E_MISSING_EXP | Missing Expiration | 400 | No |
Infrastructure errors
| Code | Title | HTTP | Retriable |
|---|---|---|---|
E_JWKS_FETCH_FAILED | JWKS Fetch Failed | 503 | Yes |
E_RATE_LIMITED | Rate Limited | 429 | Yes |
E_CIRCUIT_BREAKER_OPEN | Circuit Breaker Open | 503 | Yes |
E_INTERNAL | Internal Error | 500 | Yes |
Control errors
| Code | Title | HTTP | Retriable |
|---|---|---|---|
E_CONTROL_DENIED | Control Decision Denied | 403 | No |
E_CONTROL_REVIEW_REQUIRED | Review Required | 202 | Yes |
Identity errors
| Code | Title | HTTP | Retriable |
|---|---|---|---|
E_IDENTITY_MISSING | Identity Missing | 401 | No |
E_IDENTITY_INVALID_FORMAT | Identity Invalid Format | 400 | No |
E_IDENTITY_EXPIRED | Identity Expired | 401 | No |
E_IDENTITY_NOT_YET_VALID | Identity Not Yet Valid | 401 | Yes |
E_IDENTITY_SIG_INVALID | Identity Signature Invalid | 401 | No |
E_IDENTITY_KEY_UNKNOWN | Identity Key Unknown | 401 | Yes |
E_IDENTITY_KEY_EXPIRED | Identity Key Expired | 401 | No |
E_IDENTITY_KEY_REVOKED | Identity Key Revoked | 401 | No |
E_IDENTITY_BINDING_MISMATCH | Identity Binding Mismatch | 400 | No |
E_IDENTITY_BINDING_STALE | Identity Binding Stale | 401 | Yes |
E_IDENTITY_BINDING_FUTURE | Identity Binding Future | 400 | No |
E_IDENTITY_PROOF_UNSUPPORTED | Identity Proof Unsupported | 400 | No |
E_IDENTITY_DIRECTORY_UNAVAILABLE | Identity Directory Unavailable | 503 | Yes |
Verifier errors
| Code | Title | HTTP | Retriable |
|---|---|---|---|
E_VERIFY_RECEIPT_TOO_LARGE | Receipt Too Large | 413 | No |
E_VERIFY_MALFORMED_RECEIPT | Malformed Receipt | 400 | No |
E_VERIFY_ISSUER_NOT_ALLOWED | Issuer Not Allowed | 403 | No |
E_VERIFY_KEY_FETCH_BLOCKED | Key Fetch Blocked | 403 | No |
E_VERIFY_KEY_FETCH_FAILED | Key Fetch Failed | 502 | Yes |
note
The verifier category contains 17 total error codes. The full list is available in the kernel specification.
Using error codes
error-handling.ts
import { PeacError, PEAC_ERRORS } from '@peac/kernel';
import { verifyReceipt } from '@peac/protocol';
try {
const result = await verifyReceipt(receipt, {
issuer: 'https://trusted.example.com',
});
} catch (err) {
if (err instanceof PeacError) {
console.log(err.code); // 'E_INVALID_SIGNATURE'
console.log(err.category); // 'verification'
console.log(err.message); // 'Invalid Signature'
console.log(err.retriable); // false
// Programmatic handling by error code
if (err.code === PEAC_ERRORS.E_JWKS_FETCH_FAILED.code) {
// Retry with backoff -- this error is transient
}
}
}
info
All 139 error codes are available as TypeScript constants via @peac/kernel. The normative source of truth is specs/kernel/errors.json -- the TypeScript constants are generated from this file, and CI checks for drift.