Skip to content

Pinboard's own failures return a status and a JSON body with one human-readable error string. There are no error codes; match on status first, then on the exact string.

{ "error": "no live backends for namespace" }
FieldTypePresentMeaning
errorstringalwaysWhat failed. Strings ending in : … carry the offending value.
reregistertrue409 from worker routesThe session is gone. Register again.
supersededtrue409 from heartbeatAnother registration displaced this one. Stop; do not re-register with the same epoch.

Exceptions to the JSON shape:

  • Invalid ids on the data plane and proxy failures (502, 504) are text/plain.
  • /readyz and the 502 for a client that aborted before the forward have an empty body.
  • WebSocket upgrades that fail get a bare status line with no body; see Proxy a request.
  • Responses from a worker pass through unchanged. A worker's own errors use its framework's shape (pinned: {"detail": "..."}).

Retry-After

Every 503 Pinboard produces carries Retry-After in whole seconds, at least 1. /readyz is the one 503 without it.

Status codes

StatusMeaningRetry
400Malformed request: bad JSON, body schema, field rule, id charsetNo; fix the request
401No credential where one is required, or a rejected credentialNo; fix the credential
403Credential valid but out of scope, or instance attestation failedNo
404Unknown route or namespace with no registered workersMaybe; workers may register later
409Worker session conflict or goneRe-register, unless superseded
413Request body over the capNo
500Unhandled server errorYes, with backoff
502Worker unreachable or failed mid-requestYes
503Refusal: placement not possible right nowYes, after Retry-After
504Worker sent no response headers within forwards.timeoutMs (30 s)Yes
508Instance call chain deeper than 50No

Error registry

Every error Pinboard returns, grouped by where it is raised. … stands for the interpolated value.

Any route

StatuserrorWhen
404not foundPath outside basePath; unknown /registry/* path or wrong method; WebSocket upgrade to a path that is not /{namespace}/{id}
500internal errorA handler threw

Request bodies (POST /registry/*)

StatuserrorWhen
400invalid jsonBody is not JSON
413body too largeBody over 1 MiB (8 MiB on register), by Content-Length or by bytes read
400expected { … }Body fails the route's schema. The string lists the expected fields.

Registry authentication

StatuserrorWhen
401unauthorizedNo credential accepted, or a provider rejected it
403forbiddenMissing the route's scope; malformed pinboard claim; account mismatch; target outside the claim scope
503not the serving fleetThis node does not hold the fleet license or failed cluster membership. Not raised by /registry/health.

Register

StatuserrorWhen
400namespace must be '/' plus a single path segment: "…"A namespaces entry is malformed
400hostname is required in hostname-aware modeHostname-aware, hostname absent
400invalid hostname: "…"hostname is * or holds whitespace, / or :
400invalid env: "…"Same rule for env or an envs value
400envs key is not a registered namespace: …envs names a namespace not in namespaces
400instances key is not a registered namespace: …instances names a namespace not in namespaces
400hostname, env, envs, takeover, and nonzero epoch require hostname-aware modeSingle-hostname mode, a hostname-aware field present
400registration probe failedThe challenge probe to advertiseUrl failed
403namespace not allowed: …Namespace outside claims.pinboard.namespaces
403backend host not allowed: …advertiseUrl host outside allowedBackendHosts
403advertiseUrl port not allowed: …Port outside allowedPorts
403hostname not allowed: …Hostname-aware, outside hostnames
403env not allowed: …Hostname-aware, outside envs
403advertiseUrl is not a valid URLadvertiseUrl does not parse
403advertiseUrl scheme not allowedScheme is not http: or https:
403advertiseUrl must not carry credentialsURL has userinfo
409client belongs to another accountclientId was registered by another principal
409hostname … is bound to env … at epoch …, not … — register with a higher epoch to displaceHostname-aware binding conflict
409env … agreed takeover … at epoch …, not … — register with a higher epoch to displaceHostname-aware takeover conflict

Heartbeat, release, tag, deregister

StatuserrorExtra fieldWhen
409unknown sessionreregisterSession unknown or its lease expired
409registration voided: challenge value mismatch on the advertise URLreregisterHeartbeat probe answered another worker's value
409registration superseded: … now bound to env … at epoch …supersededHeartbeat: a higher-epoch registration took the binding
400invalid namespaceRelease or tag: malformed namespace
400namespace not registered: …Release or tag: the session did not register that namespace

Operator routes

StatuserrorWhen
400invalid namespaceOverview: malformed ns
400empty tagOverview: tag= with no value
400namespace must be '/' plus a single path segment: "…"Wind down: malformed namespace
400env is required in hostname-aware modeWind down: hostname-aware, env absent
400env requires hostname-aware modeWind down: single-hostname, env present
400invalid env: "…"Wind down: malformed env
403namespace not allowed: …Wind down: namespace outside the claim
403env not allowed: …Wind down: env outside the claim
500metrics collection failed/metrics snapshot threw

Data plane: request checks

StatusBodyWhen
400id must be non-empty (text)Empty id segment
400id must be at most 256 characters (text)Long id
400id must contain only [A-Za-z0-9._~-] (text)Other characters, including percent-encoded ones
404unknown namespacePath has no id segment, or no worker ever registered the namespace (for the request's hostname)
400missing Host headerHostname-aware, no Host
401invalid credentialA provider rejected the credential
401authentication requiredRule needs a credential, none accepted
403namespace not allowedNo data-plane rule for the namespace
403insufficient scopeCredential holds none of the rule's scopes

Data plane: instance attestation

StatuserrorWhen
403caller attestation requires session credentialsPinboard-From without Pinboard-Session and Pinboard-Session-Secret
403malformed subrequest depthPinboard-Subrequest-Depth is not 1–9 digits
403unknown sessionSession unknown or expired
403invalid session secretSecret does not match the session
403malformed caller claimPinboard-From is not {namespace}/{id} with a valid id
403caller placement mismatchThe claimed instance is not placed on that session
403target outside caller scopeThe caller's worker did not register the target namespace, or (hostname-aware) the target's hostname or env differs from its registration
508subrequest depth exceededDepth over 50

Data plane: refusals

All 503 with Retry-After.

errorWhenRetry-After
not the serving fleetNode not licensed to serve1
no live backends for namespaceNamespace registered, no placeable worker (all dead, draining, degraded or near lease end)1
registry cold start, retryThe id's bucket is inside its cold-start window (one lease after first use)remaining window
no live workers for hostnameHostname-aware: no binding for (Host, namespace), or no placeable worker1
hostname binding displaced, retryHostname-aware: binding displaced within the last lease; unplaced ids waitremaining window
hostname bindings inconsistent, retryHostname-aware: env has no takeover binding1
takeover in progress, retryPlaced on another hostname, wind_down takeover fenceduntil the fence
placement held by another hostnamePlaced on another hostname, takeover deny1
worker inflight cap exceeded, retryWorker has forwards.maxInflight (1024) forwards awaiting headers1
worker refused activation, retryWorker answered Pinned-Refusal: lease-unhealthy and re-placement was not possible1

Data plane: forwarding

StatusBodyWhen
502bad gateway (text)Worker unreachable or the connection failed before headers
502emptyClient aborted before the forward was sent
504upstream timeout (text)No response headers within forwards.timeoutMs