Error codes
Every failure a secret operation can report maps to one stable, snake_case
code. Codes are a compatibility contract: they are append-only, never
renamed and never reused. Messages are for humans and may change.
Where you meet them:
- The CLI exits with status
1and, in--output jsonmode, prints{"error":{"code":"…","message":"…"}}on stderr. - Audit rows record the code in their
detailcolumn, never a value. - SDKs map codes to typed errors, each carrying a hint that says what to do.
Messages carry names, versions and timestamps only. No error ever contains a secret value.
| Code | Meaning | Message format | Retry later? |
|---|---|---|---|
not_found |
The named secret does not exist (and is not in the deleted state). | secret '{name}' was not found |
|
version_not_found |
The secret exists but the requested version does not. | version '{version}' of secret '{name}' was not found |
|
deleted |
The secret has been soft-deleted and must be recovered before use. | secret '{name}' is deleted; recover it before use |
|
deleted_conflict |
A soft-deleted secret with this name blocks creating a new one. | a deleted secret named '{name}' exists; recover or purge it first |
|
not_deleted |
Recovery or purge was requested for a secret that is not deleted. | secret '{name}' is not in the deleted state |
|
disabled |
The version is disabled by policy. | secret '{name}' version '{version}' is disabled |
|
not_yet_valid |
The version’s activation time has not been reached. | secret '{name}' version '{version}' is not valid before {not_before} |
yes |
expired |
The version’s expiry time has passed. | secret '{name}' version '{version}' expired on {expires_on} |
|
invalid_name |
The name does not satisfy the naming rules. | invalid name '{name}': {reason} |
|
invalid_argument |
A caller-supplied argument was rejected. | invalid argument: {0} |
|
permission_denied |
The caller is authenticated but not authorised. | permission denied: {0} |
|
locked |
The vault could not be unlocked (wrong passphrase, missing key, …). | vault is locked: {0} |
|
vault_not_found |
The vault does not exist. | vault '{name}' was not found |
|
vault_exists |
A vault with this name already exists. | vault '{name}' already exists |
|
manifest |
A project manifest could not be read or is invalid. | manifest error: {0} |
|
crypto |
A cryptographic operation failed (authentication failure, bad key, …). | cryptographic failure: {0} |
|
storage |
The storage backend failed. | storage failure: {0} |
|
io |
An I/O operation failed. | i/o failure: {0} |
|
unsupported |
The backend does not implement this operation. | unsupported operation: {0} |
|
migration_required |
The vault is in an older on-disk format. Opening it is refused until the migration is requested explicitly, because the legacy format is unauthenticated and a downgraded file could otherwise be laundered through the migration. | vault '{name}' uses schema {schema}; run sourceorrery vault migrate {name} to upgrade it (only do this for a file you trust) |
Retry later marks codes for which SecretError::is_transient is true:
calling again later could succeed without administrative action.
Source of truth: crates/sourceorrery-core/src/error.rs.