Penv Cloud
Start free
Docs
Referencesince 1.0.0-alpha.3

Error codes

Every code penv and our API answer with: exit code or HTTP status, cause, and fix, for the CLI, the API, SCIM and the AWS connect callback.

Codes from the penv CLI, our API, our SCIM endpoint and the AWS connect callback. Schema diagnostics: the .env.schema format.

CLI error shape

{
  "error": "no_credential",
  "message": "you are not signed in on this machine.",
  "fix": "Run penv login. On a server or in CI, set PENV_TOKEN."
}

fix is your next action. approval_required adds approval, url and expiresAt for the replay.

penv prints this JSON when stdout is not a terminal, with --json (global options), or under a detected agent; otherwise one line: error:, message, fix.

Exit codes

CodeNameMeaning
0okThe command did what it says.
1errorUnclassified failure; the message names the cause.
2authNot signed in, or the credential was rejected.
3validationThe schema or the values did not pass.
4confirmationA person has to confirm. The JSON carries the command you replay.
5no_credentialNo credential is available and none can be obtained.
6environment_refusedThis identity may not read that environment, or its values are write-only.

Once the child starts, penv run exits with the child's exit code, not its own.

Every code the command line answers with

Codes penv 1.0.0 raises, by exit. "Reinstall": curl -fsSL https://penv.cloud/install | sh (install the CLI).

Exit 1

CodeCauseFix
ambiguousWe answered ambiguous: a name in the address matches several projects or environments.Rename the duplicate in the console.
ambiguous_output--output names one file for several targets.penv gen per target.
bad_urlPENV_URL is not an address penv sends a credential to (below).Fix or unset it.
cancelledA picker was left, or a typed name did not match.Run it again.
cloud_failedA client failure with no better name.Retry; then penv check.
hook_existspenv scan found a git hook it did not write.Add penv scan --staged to it.
invalid_config.penv/config.toml is not valid TOML.Fix the named line.
keychainThe OS keychain would not open.Unlock it, or set PENV_TOKEN.
live_leasesCredentials minted there are still live.Revoke them, or wait.
managed_installnpm, Homebrew, Nix, winget or Scoop owns the binary.The manager's command
no_commandpenv run got nothing to run.penv run -- <command>
no_echo_offThe terminal will not stop echoing.Pipe the value on stdin.
no_git, not_a_repositorypenv scan has no git, or no repository.Name the files: penv scan <PATH>.
no_keychainNo persistent keychain for an enrolled key.Use PENV_TOKEN.
no_org, no_such_org, org_requiredYour account is in no workspace, none by that name, or several.Create one, or pass --org.
no_project, project_required, not_cloudNo cloud project yet, or this folder links none.penv push, -p <project>, or penv pull to link.
no_schemaNo .env.schema here or above.penv init
no_secretpenv machine enroll got no one-time secret.Pass the console's secret (penv machine).
not_foundThat project or environment does not exist on our side.ls under penv project or penv env.
quota_exceededYour plan's project limit is reached.Billing and plans
rate_limitedWe or the release host throttle this identity.Wait for the named reset (rate limits).
server_errorWe answered 5xx twice.Retry later.
server_refusedWe answered a status penv has no name for.Read the status in the message.
spawn_failedThe penv run command could not start.Check it is on PATH.
child_failed, encrypt_failed, no_entropy, random_unavailable, unexpected_answerWaiting on the penv run child, encrypting, or the random source failed, or we answered a full read as unchanged.Retry.
unknown_command, unknown_harness, unknown_shellNo such command, guard harness or completion shell.penv help, penv guard, penv completions
unknown_provider@penv= or --provider names no provider penv has.One the message lists.
unknown_targetNo language target by that name, or no build for this machine.A listed target, or build from source.
unreadable_file, unwritable_fileA file could not be read or written.Check path and permissions.
unreadable_input, unreadable_selectionNo value on stdin or the terminal, or an unlisted choice.Pipe it, or pick a listed choice.
untrusted_ca_bundleSSL_CERT_FILE is unreadable, holds no certificate, or is writable by you under an agent.Unset it, or name a system bundle.
undecryptableWe hold the value and cannot decrypt it, usually because your workspace key was revoked. It still exists.Restore the key (BYOK); do not overwrite the value.
unwritable_valueThe value holds a ' with a ", \, $ or function call, a carriage return, or a line break with a " or \ (generated .env).Change it, or read it with penv run.
lsp_endedThe editor closed penv lsp without a shutdown request.Restart the language server from the editor.
value_on_the_command_linepenv set takes no --value.Pipe it on stdin, or use the prompt.

penv upgrade codes, all exit 1:

CodeCauseFix
binary_lostThe swap left no binary in place.Reinstall.
invalid_version, channel_unavailableThe argument is not latest, next or a version, or penv.cloud does not answer for that channel.penv upgrade, or pin with PENV_VERSION and the installer.
checksum_mismatchThe download does not match its checksum.Retry; report a repeat.
missing_asset, no_checksumNo binary, checksum, signature or digest for this machine.Reinstall.
no_current_exepenv could not read its own path.Reinstall.
no_release, unreadable_release, release_unreachableThe release address answered 404, garbage, or nothing.Retry later, or reinstall.
signature_invalid, signature_missingThe checksum file lacks a penv release key signature.Reinstall; report it.
unsigned_buildThis build carries no release key.Reinstall.
unsupportedThe provider @penv= names does not declare what this command needs, so penv sends it no request.Name a provider that does, with --provider or @penv=<provider>:org/project.
unwritable_binaryThe binary could not be replaced.Write access, or reinstall.

bad_url: https anywhere; plain http only for 127.0.0.1, localhost and [::1]. penv upgrade --check answers only invalid_version, unknown_target, untrusted_ca_bundle, the release-reading codes and unsigned_build (upgrade penv).

Exit 2

CodeCauseFix
agent_sessionpenv login, pull, push --prune, penv bundle or penv decrypt under an agent.Run it from your terminal.
approval_deniedA person refused the reveal.Ask them, then penv reveal.
clonedYour host's identity was used from a second machine, so we locked it.A credential leaked
denied, expiredSign-in denied, or your login or device code expired.penv login
forbiddenYour identity lacks the role. Servers and CI tokens never create, rename or delete.Sign in as a person, or ask for the role.
org_ambiguousThe org in @penv= names more than one workspace you belong to.Rename one workspace in the console so the slugs differ.
unauthorizedWe rejected your login or token.penv login, or replace PENV_TOKEN.

Exit 3

CodeCauseFix
bundle_unreadable, invalid_bundle_key, no_bundlePENV_BUNDLE_KEY is malformed, wrong, or has no bundle for that environment.The key penv bundle printed, or bundle again.
cannot_seal, proxy_failed, no_home, write_failedA sealed run cannot place a placeholder, start its proxy, or write its certificates.Fix the key's type, URL or @hosts; set HOME.
hosts_unpinned, hosts_uncomputedA computed @hosts has no pin, differs from its pin, or cannot be computed.penv check --pin-hosts, after fixing the @hosts the message names.
decrypt_failed, invalid_local_key, no_local_keyAn enc:v1: value needs a local key this machine lacks, or PENV_LOCAL_KEY is not 64 hex characters.Set PENV_LOCAL_KEY, or penv set the value again.
dot_nameAn org, project or environment name is only dots.Give it a letter or digit, in the console and in .env.schema.
dynamicWe generate that key's value on demand.Edit it in the console.
empty_valuepenv set got nothing to write.Pipe a value, or penv unset.
exists, name_requiredThat environment name is taken, or a name has no letters or digits.Another name (penv env ls).
guard_failedA harness file or guard folder did not merge (penv hook answers 1).Fix it, then penv guard.
invalid_environmentThe environment name is not a usable file name, or is reserved (local, schema, example...).Letters, digits, - and _.
invalid_keyThe key name is not upper snake case.Rename it.
invalid_schema.env.schema does not parse.penv check
name_invalidA pushed key name is not upper case.Rename it in .env.schema and your value files.
no_such_environmentpenv push --env names an environment the project lacks; the message lists the others.penv env new, or a listed one.
no_valueThe key has no value in that environment.penv set
nothing_to_pushThe environment's value files are missing or empty; we are never contacted.Write values, or penv set <KEY>.
org_mismatchpenv push --org contradicts the @penv header.Drop --org, or change the header.
output_outside_repo, target_failedpenv gen output would land outside the repository, or a target folder will not load.Fix the named path or folder.
project_takenAnother project in your workspace already has that name.Pick another name, or point @penv= at the existing project.
reserved_namepenv run got a key whose variable changes how the command runs (NODE_OPTIONS, LD_PRELOAD, PATH...), or that is not a variable name.Rename the parameter.
unknown_keypenv check or penv why got an undeclared key.Declare it; penv ls lists keys.
invalid_reference, invalid_value, unresolved_valueA computed value failed: a bad penv() address, a random() length outside 8 to 512 or written as random(32) instead of random(length=32), a [url], [json.KEY] or [hash] entry that would expose a secret, or another reference.Fix the part the message names.

Exit 4

CodeCauseFix
approval_required, approval_expired, approval_redeemedSee the four approval codes.Approve, or penv reveal again.
approval_mismatch, no_approval, approval_unreadableThe id covers another key, is not on our side, or we did not say which key it covers (nothing spent).penv reveal for this key.
confirmation_requiredDeleting a project or environment from an agent or a non-terminal.Run the replay command in the JSON yourself.

Exit 5 and 6

CodeExitCauseFix
no_credential5This host can prove nothing.penv login, or set PENV_TOKEN.
credential_withheld5The API root comes from .penv/config.toml, so penv withholds PENV_TOKEN, CI and AWS proofs.penv login there, or set PENV_URL.
offline5We are unreachable, and penv has no value files for this environment and, for development, no saved copy.Reconnect.
environment_refused6Your identity has no access to that environment.Ask for a role, or change --env.
redacted6The key is in a write-only environment and this identity is not a workload. The value exists.Read it from a workload identity, or set it in .env.<env>.local. Do not overwrite the value.

Since 1.0.0-beta.3

penv 1.0.0-beta.3 added these codes. The last column is what 1.0.0-beta.2 answers instead.

CodeExitCauseIn 1.0.0-beta.2
invalid_version, channel_unavailable1penv upgrade got a bad argument, or we do not serve that channel yet.penv upgrade takes no argument.
project_taken3The project name exists in your workspace.ambiguous
org_ambiguous2Two workspaces you belong to answer to the @penv= org.ambiguous
name_invalid3A pushed key name is not upper case.server_refused, 400
undecryptable1We hold the value and cannot decrypt it, usually because your workspace key was revoked.server_refused, 409
redacted6The key is in a write-only environment and this identity is not a workload.Key reported as missing; reveal gets server_refused, 409

Since 1.0.0-beta.4

CodeExitCauseFix
unsupported1The provider @penv= names does not declare what this command needs, so penv sends it no request.Name a provider that does, with --provider or @penv=<provider>:org/project.

undecryptable and redacted are never an absence: the value still exists. For undecryptable, restore the key (BYOK). For redacted, read it from a workload identity or set a local override. Do not overwrite the value.

What penv.cloud answers

Every /api/v1 route answers JSON; our error body is { "error": "<code>" }. The schema-shaped, name and size refusals add detail naming the wrong part of the body, and a schema_invalid about @hosts adds "field": "hosts", or "field": "hostsExpr" for a computed one. Operations: API reference. 401 and 403: authentication.

StatusCodeCause
400name_required, keys_required, address_required, body_required, value_or_schema_required, token_required, signed_request_required, signed_challenge_required, credential_id_required, enrollment_requiredThe part of the request the code names is missing.
400name_invalid, key_invalidA key name or path, or the key an approval asks for, is not usable. A name holds letters, digits, _, - and .; a path holds no whitespace, control character or shell character. detail says which.
400value_must_be_a_stringThe value in the body is not a string.
400schema_invalidThe per-key schema is not the shape penv schema --json emits.
400ttl_must_be_an_integerA lease or exchange lifetime (ttlSeconds) is not a whole number of seconds.
400ttl_too_shortAn exchange's ttlSeconds is under 60.
400audience_not_workspace_idAn OIDC or AWS exchange named the workspace by its slug. Use the workspace id (the Organization ID under Settings, Organization) as the token audience or the signed x-penv-cloud-org header.
400invalid_requestAn app-connection request has a missing, repeated or malformed parameter, or a bad ttlSeconds (connect an app).
400invalid_redirect_uriThe app's redirect_uri is not one registered for it.
400invalid_grantA connect code or app grant is wrong, expired, used, replaced or revoked. Presenting a replaced grant revokes the connection.
401invalid_clientNo registered app has that client_id, or the app was deleted.
401expiredYour credential expired.
401unauthorizedNot accepted; revoked and unknown read the same.
401replayedA keypair challenge nonce was used twice.
403forbiddenValid, without this permission or environment.
403app_unavailableThe app is suspended (register an app).
403app_unverifiedThe app is in testing mode and the person is not in the organization that owns it (register an app).
403deniedA person denied the device-code sign-in.
403refusedAn OIDC exchange, delivery or plain, from a pull_request_target run.
403lease_api_disabledLeases are off for this environment.
404not_foundNo such project, environment, key, approval or route in scope.
409dynamicWe mint the key on request; it is never a stored value.
409change_approval_requiredThe environment requires approval and this change has none yet. We filed a request; requests in the body names it.
409machine_change_requires_approvalThe environment requires approval, and a machine identity cannot file a request. Make the change as a person, or turn off approvals for the environment.
409change_conflictYou have an open request for a different change at this key. Save the change you asked for, or withdraw that request under Approvals; requests names it. Other keys in the same push were sent for approval; filed names those requests.
409redactedThe environment is write-only and the credential is not a workload identity. The value exists.
409clonedThe keypair generation counter does not match. The identity is revoked.
409quota_exceededThe plan's project limit is reached.
409ambiguousA project or environment slug in the address matches more than one on our side.
409project_takenAnother project in your workspace already answers to that name's slug, on create or rename.
409org_ambiguousThe org slug in an address names more than one workspace you belong to.
409undecryptableWe hold the value and cannot open it, for instance because your workspace key was revoked.
409existsThe project already has an environment by that name.
409live_leasesA credential minted in what you delete is still live.
409engine_unavailableThe engine behind a dynamic key did not answer.
410expiredThe device code expired before approval.
413value_too_largeOne value is over 256 KiB (262,144 bytes of UTF-8). detail names the key and its size.
413too_many_keysOne push carries more than 1,000 keys. Push it in parts.
413body_too_largeThe request body is over 2 MiB for one value, or 4 MiB for a push.
421wrong_regionThe credential belongs to another residency cell. host names the API host that holds it.
428authorization_pendingNobody has approved the device code yet. Keep polling.
429rate_limitedAn IP or plan limit. retry-after gives the wait.
429slow_downDevice-code polling is faster than the interval.
429ceiling_reachedThe abuse ceiling on dynamic leases.
500internalWe failed on our side. Retry once.
500mint_failedThe engine accepted the request and produced nothing.
503unavailableA dependency is unreachable or unconfigured. Retry once.

penv retries any other 5xx from us once after a second, then reports server_error naming the status. Back-off for 429: rate limits.

The four approval codes

We answer every approval state of a penv reveal under an agent with a 409. Flow: coding agents.

Server codeMeaningCLI codeExit
approval_pendingUnanswered, or an open request for this key and session exists.approval_required, with page and expiry4
approval_deniedA person refused it.approval_denied2
approval_expiredThe ten minutes ran out.approval_expired4
approval_redeemedThe id was already spent.approval_redeemed4

A 404 from the redeem route becomes no_approval. penv raises approval_mismatch itself, before it asks us to redeem, so a mismatched id is never spent.

SCIM errors

Our directory endpoint answers RFC 7644 error objects, the shape Okta and Entra parse. Content type: application/scim+json;charset=UTF-8. status is a string; scimType carries an RFC detail keyword when one applies.

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "status": "409",
  "scimType": "uniqueness",
  "detail": "A user with that userName already exists."
}

We answer an unrecognized failure with a 500 whose detail is always "The request could not be completed.", so no stack trace reaches a directory token holder.

AWS connect callback

Success: 200 with the lifecycle secret on a fresh create, 200 {} on a replayed create, otherwise 204.

CodeStatusCause
invalid_request400The body has the wrong shape.
unauthorized401The token or External ID did not hold.
conflict409The stack conflicts with what your workspace already has.
upstream502AWS answered something we cannot act on.
retry503retry-after is 5 seconds.
unexpected500Nothing else fits.

An unknown, expired, already claimed or exhausted token, a wrong External ID and a bad lifecycle secret all get the same 401, so the endpoint reveals nothing about which.