Error Codes
Overview
Section titled “Overview”PCP errors exist at three layers. The outermost layer is the wire protocol, which uses HTTP-style numeric codes in ErrorResponsePayload { code, message } on the client socket. The middle layer is the core PcpError enum, which the daemon uses internally for structured error handling. The innermost layer covers transport and framing errors that arise before any protocol logic runs.
Capability-level failures do not arrive as error frames. They return success: false results with an error description in the response payload. This distinction matters because it separates “the protocol broke” from “the capability failed.”
Wire Error Codes
Section titled “Wire Error Codes”These codes travel over the socket in ErrorResponsePayload. They indicate problems at the protocol or daemon level, not at the capability level.
| Code | Meaning |
|---|---|
| 400 | Unsupported message type, malformed payload, or decode failure |
| 404 | Capability or app not found |
| 429 | Rate limit exceeded (100 requests/second/connection) |
| 500 | Adapter or execution failure |
| 503 | Daemon unhealthy or adapter unavailable |
| 504 | Execution timeout (30 seconds) |
A 400 means the client sent something the daemon cannot parse. This is a client bug, not a transient failure. A 404 means the target capability or application does not exist in the registry. A 429 is the rate limiter rejecting a request before it reaches the dispatcher. A 500 is a catch-all for adapter-level failures. A 503 means the daemon itself is in a bad state (for example, an adapter crashed and has not been replaced). A 504 means the capability took too long to execute.
The 429 response fires immediately, before the request reaches the dispatcher. This is intentional: rate-limited requests should not consume any resources beyond the rate check itself.
PcpError Variants
Section titled “PcpError Variants”The core PcpError enum covers every failure mode the daemon can encounter. These are structured errors that carry context about what went wrong, making them useful for logging, debugging, and client-side error handling.
Capability and Registry Errors
Section titled “Capability and Registry Errors”| Variant | Meaning |
|---|---|
CapabilityNotFound |
The requested capability does not exist in the registry |
AdapterUnavailable |
The adapter for the target capability is not running or has crashed |
RegistryError |
A registry operation (register, unregister, query) failed |
Permission and Confirmation
Section titled “Permission and Confirmation”| Variant | Meaning |
|---|---|
PermissionDenied |
The requester lacks the auth level for this capability |
ConfirmationError |
The confirmation gate rejected the request (expired, denied, or malformed token) |
Execution and Detection
Section titled “Execution and Detection”| Variant | Meaning |
|---|---|
ExecutionFailed |
The capability invocation returned an error from the adapter or target app |
DetectionFailed |
The adapter could not detect capabilities for the target application |
Timeout |
The operation exceeded its configured timeout |
Integrity and Rate Limiting
Section titled “Integrity and Rate Limiting”| Variant | Meaning |
|---|---|
AuditError |
Writing to or reading from the audit log failed |
SupervisionError |
The supervision or health monitoring system reported an error |
RateLimitExceeded |
The per-connection rate limit was exceeded |
Input and Protocol
Section titled “Input and Protocol”| Variant | Meaning |
|---|---|
InvalidParameters |
One or more parameters failed validation (reason field explains what) |
TransactionAborted |
A multi-step transaction was aborted (rollback attempted or skipped) |
SerializationError |
Structured data could not be serialized or deserialized |
Connection and Auth
Section titled “Connection and Auth”| Variant | Meaning |
|---|---|
ConnectionError |
The underlying IPC connection dropped or failed to establish |
AuthenticationFailed |
Auth handshake failed (reason field explains what) |
ManifestValidationError |
A capability manifest failed structural or schema validation |
Event Errors
Section titled “Event Errors”| Variant | Meaning |
|---|---|
EventError |
Publishing or delivering an event failed (subscription issues, channel overflow) |
IpcError (Tier 1 Transport)
Section titled “IpcError (Tier 1 Transport)”IpcError covers failures on the Tier 1 IPC path. These occur when the daemon talks to Tier 1 applications over Unix domain sockets.
| Variant | Meaning |
|---|---|
ConnectionFailed |
Could not establish a connection to the target app’s socket |
Protocol |
The app sent a message that violates the PCP framing protocol |
Serialization |
Postcard or JSON encode/decode failed on the IPC path |
AppNotReachable { app_id } |
The app’s socket exists but the app is not responding |
UnexpectedMessageType |
Received a message type that does not belong in the current exchange |
ConnectionClosed |
The app closed the connection mid-exchange |
ProtocolError (Framing)
Section titled “ProtocolError (Framing)”ProtocolError covers low-level framing failures. These occur during deserialization of raw bytes into protocol messages, before any semantic processing happens.
| Variant | Meaning |
|---|---|
BadMagic |
The frame header magic bytes do not match the expected value |
BadVersion |
The protocol version in the header is not supported |
Truncated |
The frame is shorter than the header indicates |
ChecksumMismatch |
The frame checksum does not match the payload |
UnknownMessageType |
The message type code is not recognized |
Postcard |
Postcard deserialization failed on the frame payload |
Io |
An underlying I/O error occurred while reading or writing the frame |
Error Response Format
Section titled “Error Response Format”Wire errors follow the ErrorResponsePayload structure:
{ "code": 404, "message": "capability not found: mail.send for app com.example.mailclient"}Capability-level failures arrive differently, as success: false results:
{ "id": 1, "result": { "success": false, "error": "ExecutionFailed", "reason": "target element no longer exists" }}The distinction matters for clients. A wire error (code in the 400-504 range) means the request itself was rejected. A success: false result means the request was valid but the capability could not execute it.
Retry Guidelines
Section titled “Retry Guidelines”Not all errors should be retried automatically.
Never retry parse errors (400), malformed payloads, or manifest validation failures. The payload or configuration itself is broken.
Respect rate limits (429). Back off with exponential delay. Start at 1 second, double on each failure, cap at 30 seconds. The rate limit is 100 requests per second per connection.
Retry transient failures once. Connection errors (503), timeouts (504), and adapter unavailability may resolve on the next attempt. If the same request fails twice in a row, stop and report.
Re-query state before retrying 404 errors. If a capability or app was not found, something may have changed. Fetch a fresh registry state before retrying.
Stop after three consecutive failures with an execution error. Looping indefinitely wastes resources and may amplify an already-degraded situation.