Error codes
Broker HTTP API
Section titled “Broker HTTP API”The broker refuses a request with an HTTP status and a JSON body {"code": "…", "error": "…"}. agent-secrets prints a refusal as <error> (<code>). A message shown as an error’s own text may arrive wrapped in more detail; (varies) marks a message built at run time.
| Code | Status | Message | Where |
|---|---|---|---|
ACCOUNT_NOT_LISTED |
403 | this ServiceAccount does not log in as this service | POST /v1/launcher-credentials/token |
ALREADY_ENROLLED |
409 | this runtime is already enrolled and live | POST /v1/enrollments |
APPROVER_REQUIRED |
400 | approver is required | GET /v1/grantsGET /v1/launcher-credentialsGET /v1/pendingPOST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/grants/{id}/revoke-by-approverPOST /v1/launcher-credentials/{id}/revoke-by-approver |
CODE_MISMATCH |
403 | confirmation code does not match | POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/deny |
CODE_REQUIRED |
400 | code is required code is required to decide a machine login |
POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/machine-logins/lookup |
CREDENTIAL_ID_INPUT |
400 | launcher credential ids are UUIDs | POST /v1/launcher-credentials/{id}/revoke-by-approverPOST /v1/operator/machines/{id}/revoke |
DATABASE_UNAVAILABLE |
503 | ping Postgres failed: a dependency the broker needs is unavailable read launcher credential failed: a dependency the broker needs is unavailable verify launcher proof failed: a dependency the broker needs is unavailable verify proof failed: a dependency the broker needs is unavailable |
GET /healthzevery Machine credential route every Renewal session proof route every Session proof route |
ENROLLMENT_ID_INPUT |
400 | enrollment ids are UUIDs | DELETE /v1/enrollments/{id}POST /v1/enrollments/{id}/renew |
ENROLLMENT_NOT_LIVE |
401 | enrollment is not live | POST /v1/enrollments/{id}/renewevery Renewal session proof route |
GRANT_CHAIN_INVALID |
403 | this grant’s approval chain no longer verifies | POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/grants/{id}/values |
GRANT_ID_INPUT |
400 | grant ids are UUIDs | POST /v1/grants/{id}/revoke-by-approverPOST /v1/grants/{id}/revokePOST /v1/grants/{id}/valuesPOST /v1/operator/grants/{id}/revoke |
GRANT_NOT_LIVE |
403 | grant is expired, revoked, or its session ended | POST /v1/grants/{id}/values |
INTERNAL |
500 | cancel request failed create enrollment failed create request failed decide credential request failed decide machine login failed list grants for approver failed list launcher credentials failed list pending requests failed lookup machine login failed machine login failed read credential request failed read credential request kind failed read enrollment failed read grant values failed read live grants failed read machine login failed read request failed read request owner failed renew enrollment failed reread secret failed revoke enrollment failed revoke grant failed revoke launcher credential failed token login failed |
DELETE /v1/enrollments/{id}GET /v1/credential-requests/{record}GET /v1/enrollments/selfGET /v1/grantsGET /v1/launcher-credentials/{pending}GET /v1/launcher-credentialsGET /v1/operator/grantsGET /v1/operator/machinesGET /v1/pendingGET /v1/requests/{id}POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/enrollments/{id}/renewPOST /v1/enrollmentsPOST /v1/grants/{id}/revoke-by-approverPOST /v1/grants/{id}/revokePOST /v1/grants/{id}/valuesPOST /v1/launcher-credentials/tokenPOST /v1/launcher-credentials/{id}/revoke-by-approverPOST /v1/launcher-credentialsPOST /v1/machine-logins/lookupPOST /v1/operator/grants/{id}/revokePOST /v1/operator/machines/{id}/revokePOST /v1/requests/{id}/cancelPOST /v1/requestsPOST /v1/secrets/{name}/reread |
INVALID_DECISION |
400 | body must be one valid JSON object: (varies) | POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/deny |
INVALID_ENROLLMENT |
400 | body must be one valid JSON object: (varies) | POST /v1/enrollments |
INVALID_KIND |
400 | kind must be “session” or “pod” | POST /v1/enrollments |
INVALID_LOOKUP |
400 | body must be one valid JSON object: (varies) | POST /v1/machine-logins/lookup |
INVALID_RENEWAL |
400 | body must be one valid JSON object: (varies) | POST /v1/enrollments/{id}/renew |
INVALID_REQUEST |
400 | body must be one valid JSON object: (varies) | POST /v1/launcher-credentials/tokenPOST /v1/launcher-credentialsPOST /v1/requests |
INVALID_REVOKE |
400 | body must be one valid JSON object: (varies) | POST /v1/grants/{id}/revoke-by-approverPOST /v1/launcher-credentials/{id}/revoke-by-approver |
INVALID_SLOT |
400 | a slot is only for a pod enrollment and must match ^[a-z][a-z0-9-]{0,62}$ | POST /v1/enrollments |
KEY_HOLDS_LIVE_CREDENTIAL |
409 | this machine login’s key already holds a live launcher credential | POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/launcher-credentials/token |
LAUNCHER_INVALID |
401 | the launcher credential is not valid this route needs a launcher proof, not a session proof |
POST /v1/enrollmentsevery Machine credential route |
MIXED_APPROVERS |
400 | the requested secrets need different approvers; request them separately | POST /v1/requests |
NOT_APPROVER |
403 | only the grant’s approver or its enrollment’s operator may revoke it only the person who approved a person’s machine login may revoke it only the record’s approver may decide it |
POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/grants/{id}/revoke-by-approverPOST /v1/launcher-credentials/{id}/revoke-by-approverPOST /v1/operator/grants/{id}/revokePOST /v1/operator/machines/{id}/revoke |
NOT_ENROLLING_CREDENTIAL |
403 | only the machine login that enrolled a pod may end its enrollment | DELETE /v1/enrollments/{id} |
NOT_FOUND |
404 | no such credential request no such grant no such machine login no such pending machine login no such request |
GET /v1/credential-requests/{record}GET /v1/launcher-credentials/{pending}GET /v1/requests/{id}POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/grants/{id}/revoke-by-approverPOST /v1/grants/{id}/revokePOST /v1/launcher-credentials/{id}/revoke-by-approverPOST /v1/operator/grants/{id}/revokePOST /v1/operator/machines/{id}/revokePOST /v1/requests/{id}/cancel |
NOT_YOURS |
403 | a session may only renew its own enrollment this request belongs to another session this request or grant belongs to another session |
GET /v1/requests/{id}POST /v1/enrollments/{id}/renewPOST /v1/grants/{id}/revokePOST /v1/grants/{id}/valuesPOST /v1/requests/{id}/cancel |
NO_SUCH_CODE |
404 | no pending machine login has this code | POST /v1/machine-logins/lookup |
OPERATOR_MISMATCH |
403 | this launcher credential enrols a different operator | DELETE /v1/enrollments/{id}POST /v1/enrollments |
POD_IDENTITY_MISMATCH |
403 | the projected token does not identify this pod | POST /v1/enrollments/{id}/renewPOST /v1/enrollments |
POD_TOKEN_EXPIRED |
403 | the projected token has expired | POST /v1/enrollments/{id}/renewPOST /v1/enrollments |
POD_TOKEN_REQUIRED |
403 | a pod enrollment’s renewal must carry its projected token | POST /v1/enrollments/{id}/renew |
PROOF_INVALID |
401 | enrollment is not live proof invalid proof invalid: not live this route needs a session proof, not a launcher proof |
GET /v1/enrollments/selfPOST /v1/requestsevery Renewal session proof route every Session proof route |
RATE_LIMITED |
429 | too many launcher credential requests; try again later too many secret rereads; try again later too many token logins for this ServiceAccount; try again later |
POST /v1/launcher-credentials/tokenPOST /v1/launcher-credentialsPOST /v1/secrets/{name}/reread |
RECORD_ID_INPUT |
400 | record ids are lowercase-hex sha256 hashes | GET /v1/credential-requests/{record}POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/deny |
RECORD_TERMINAL |
409 | request expired before its approver acted on it request is already decided this machine login expired before its approver acted on it this machine login has already been decided |
POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/deny |
REQUEST_ENDED |
503 | the request ended before the reread finished; send it again | POST /v1/secrets/{name}/reread |
REQUEST_ID_INPUT |
400 | request ids are UUIDs | GET /v1/requests/{id}POST /v1/requests/{id}/cancel |
REQUEST_INVALID |
400 | (varies) request object invalid |
POST /v1/launcher-credentials/tokenPOST /v1/launcher-credentialsPOST /v1/requests |
REQUEST_PENDING |
409 | a request for one or more of these secrets is already pending | POST /v1/requests |
REQUEST_TERMINAL |
409 | request is already decided | POST /v1/requests/{id}/cancel |
REQUEST_TOO_LARGE |
413 | request body exceeds … bytes | POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/enrollments/{id}/renewPOST /v1/enrollmentsPOST /v1/grants/{id}/revoke-by-approverPOST /v1/launcher-credentials/tokenPOST /v1/launcher-credentials/{id}/revoke-by-approverPOST /v1/launcher-credentialsPOST /v1/machine-logins/lookupPOST /v1/requests |
SECRET_NAME_INVALID |
400 | not an agent secret name | POST /v1/secrets/{name}/reread |
SECRET_NOT_IN_STORE |
404 | secret is not in the secrets store | POST /v1/grants/{id}/values |
SERVICE_CREDENTIAL |
403 | a service’s machine login has no operator; machine and grant commands are a person’s | GET /v1/operator/grantsGET /v1/operator/machinesPOST /v1/operator/grants/{id}/revokePOST /v1/operator/machines/{id}/revoke |
SERVICE_LOGS_IN_WITH_TOKEN |
400 | (varies) a service logs in with its own Kubernetes ServiceAccount token at POST /v1/launcher-credentials/token, never through a code a person approves |
POST /v1/credential-requests/{record}/approvePOST /v1/credential-requests/{record}/denyPOST /v1/launcher-credentials |
SESSION_ID_INPUT |
400 | session id must be at most 128 characters with no whitespace or control character | POST /v1/requests |
TOKEN_EXPIRED |
401 | the ServiceAccount token has expired | POST /v1/launcher-credentials/token |
TOKEN_INVALID |
401 | the ServiceAccount token does not verify | POST /v1/launcher-credentials/token |
TOKEN_LOGIN_OFF |
404 | this broker trusts no Kubernetes token issuer, so no service logs in with a token | POST /v1/launcher-credentials/token |
TOKEN_TOO_LONG_LIVED |
401 | the ServiceAccount token lives longer than an hour from its issue | POST /v1/launcher-credentials/token |
UI_INVALID |
401 | the UI bearer token is not valid | every Dispatch token route |
UNKNOWN_SECRET |
400 | no agent secret has this name | POST /v1/requests |
Host helper
Section titled “Host helper”agent-secrets-helper answers a request it refuses with one of these codes and an error message; agent-secrets prints them as <code>: <error>.
| Code | Meaning |
|---|---|
BAD_REQUEST |
Answers a request that is not one JSON object per line, names an unknown op, leaves out a field its op needs, or asks sign-launcher for anything but one of the four operator routes under this helper’s broker. |
ENROLL_FAILED |
Answers an enroll-session-key the broker refused or could not be asked; the error says why. |
IN_SESSION |
Answers sign-launcher from a process inside a registered session’s process tree, or one whose ancestry the helper cannot follow to init (a parent it cannot read, a loop, or past 64 processes), so a session’s own commands cannot act as its operator. A process that leaves its session’s tree (a double fork or setsid, reparented to init or a subreaper) is not refused, and the operator’s user can stop the helper anyway: it guards a session’s own process tree, not a boundary against code running as that user. |
KEYGEN |
Answers a register the helper could not make the new session’s signing key for; the error says why. |
LOGIN_FAILED |
Answers a login the helper could not start with the broker; the error says why. |
NOT_A_SESSION |
Answers sign, sign-request or unregister from a process that descends from no session agent-secrets register registered. |
NOT_ENROLLED |
Answers sign or sign-request for a registered session that is still enrolling: the helper holds a launcher credential, and its enroll loop has not succeeded yet. |
NO_CREDENTIAL |
Answers sign, sign-request or sign-launcher while the helper holds no launcher credential, from every restart until the operator logs the machine in: it enrolls no one, so a session has no broker identity, and the operator’s shell has no machine login to act as. A register reply for such a session carries it too, beside OK. |
PEER_UNIDENTIFIED |
Answers a caller the kernel could not identify, or one whose process exited or changed while the helper was identifying it. |
SIGN |
Answers sign, sign-request or sign-launcher when signing the proof or the request object failed; the error says why. |
UNENROLL_FAILED |
Answers an unenroll-session-key the broker refused or could not be asked; the error says why. |
agent-secrets exit codes
Section titled “agent-secrets exit codes”agent-secrets exits 0 when it is done and 1 when it failed; these are the other codes it exits with.
| Exit code | Meaning |
|---|---|
| 2 | Usage error: a flag, argument, token file, or required environment value is invalid |
| 75 | Request still waiting for a person to approve it |
| 76 | Renew reached a refusal in terminalRenewal; the worker shim must not restart it |
| 77 | Request denied |
| 126 | Register –exec command exists but could not run |
| 127 | Register –exec command was not found |
| 129 | Secret prompt received SIGHUP |
| 130 | Secret prompt received SIGINT |
| 131 | Secret prompt received SIGQUIT |
| 143 | Secret prompt received SIGTERM |