Skip to content
ocx
install

Environment & exit codes: Discovery

Part 3 of 3 of Environment & exit codes.

bootstrap.discover (used internally by Ocx() construction) resolves a binary in this order:

  1. An explicit exe= argument.
  2. OCX_SDK_EXE.
  3. PATH (the current working directory is excluded from the search on Windows).
  4. $OCX_HOME/…/current/content/bin/ocx — ocx’s own stable install symlink.

Nothing found raises OcxNotFoundError, whose message names bootstrap.ensure() as the fix.

Project.env, Project.exec, and PackageCommands.test accept extra env= entries serialized as ocx’s --env KEY[:TYPE[:SEP]]=VALUE flag. A key in the OCX_* or __OCX_* namespace is rejected with OcxError — a project cannot reconfigure how ocx itself resolves through this path. Set the corresponding OcxConfig field instead.

The exit code of the ocx process is the error category — _process maps it to a subclass, and nothing in the SDK ever classifies a failure by matching stderr text.

Code ExitCode Exception Retried by default?
0 OK — —
1 FAILURE plain OcxProcessError no
64 USAGE UsageError no
65 DATA_ERR DataError no
69 UNAVAILABLE UnavailableError no — ocx classified it non-transient
74 IO_ERR IoError no
75 TEMP_FAIL TempFailError yes — the only retry signal (RetryPolicy.retry_on default)
77 NO_PERM PermissionDeniedError no
78 CONFIG ConfigError no
79 NOT_FOUND NotFoundError no
80 AUTH AuthError no — auth failures are never retried
81 POLICY_BLOCKED PolicyBlockedError no
82 DIRTY_RC_BLOCK DirtyRcBlockError no
83 TRANSPARENCY_LOG_UNAVAILABLE TransparencyLogUnavailableError no — retrying amplifies Rekor’s rate limiting, and a later success is not restored trust
84 REFERRERS_UNSUPPORTED ReferrersUnsupportedError no
85 UNSUPPORTED_KEY_BACKEND UnsupportedKeyBackendError no
86 FORGE_CAPABILITY_UNAVAILABLE ForgeCapabilityUnavailableError no — the credential is valid and the forge was reached; an administrator has to enable job-token push on the target project or allowlist the publishing one
— (timeout, no exit code) — OcxTimeoutError no

A process killed by a signal exits with a code ocx never assigns (137 for SIGKILL, for instance); OcxProcessError.exit_code is a plain int for exactly that reason, and such an exit lands as the generic OcxProcessError rather than any per-code subclass. except OcxExecutionError is the catch shape that covers both a non-zero exit and a timeout in one clause.

Two methods default their per-call retry to None regardless of session policy: Ocx.login and package.push — see Concurrency & timeouts for why, and pass retry= explicitly to override.