Skip to navigation

Error Reference

View as Markdown

This page lists every code APF writes to its audit records or returns to a caller on the main branch. Search it for the code you see. For a diagnostic workflow, refer to Troubleshooting and Investigate a Denied Request.

Policy Service Startup

Written once per start as policy_service_startup. The first weakened control becomes the reason_code, and error.message lists all of them.

reason_codesecurity_stateCauseFix
startup.securesecureNo weakened controls.None.
startup.token_in_process_argsdegraded--bundle-source-token was passed on the command line, where other local processes can read it.Use --bundle-source-token-file.
startup.ephemeral_signing_keydegradedNo --document-signing-key, so a random key signs provenance tokens. It changes on every restart.Configure a persistent document signing key.
startup.bundle_source_unauthenticateddegradedThe HTTP source has no token.Set --bundle-source-token-file.
startup.http_bind_non_loopbackdegradedThe HTTP surface listens on a non-loopback address.Bind to 127.0.0.1, or restrict the port with a firewall.

These failures stop the policy service. The message is printed on standard error. The first four occur before the startup record is written, so they leave no audit record. The others occur after it.

MessageFix
no audit log directory configured; set --audit-log-dir or APF_AUDIT_LOG_DIR (audit_log_dir in the config file)Set the audit directory.
trust-root dir <dir> contains no `*.pub` keysInstall at least one trust root. .pem and .p256 keys also count.
load counter store: ...Restore or remove the corrupt counter file. Refer to Backup and Recovery.
--http-addr requires --http-bearer-token-file; ...Provide a token file, or remove --http-addr.
--bundle-path (or APF_BUNDLE_PATH) is required when --policy-source=localSet the bundle path.
--bundle-source-url required when --policy-source=httpSet the bundle URL.
--bundle-source-token-file <path> is empty; unset it to fetch anonymouslyWrite the token to the file, or remove the flag.
bundle verification failed: [...]The initial bundle was rejected. Refer to Bundle Rejection Reasons.
unknown --resolver: <value>Use passthrough or claims.
--claims-config required when --resolver=claimsProvide the claims file.

Bundle Rejection Reasons

A rejected bundle produces a policy_verification record with outcome refused, reason_code policy.bundle_rejected.<first reason>, the reason codes in rejection_reasons, and the full detail in error.message. With the HTTP source, the policy service picks the manifest from the archive by trying each .yaml file until one verifies and parses. If none does, for example because the signature is invalid or the signing key is not trusted, it never reaches the verification step: no policy_verification record is written, and the only message is find bundle manifest: no bundle manifest (.yaml) found in extracted archive at <path> in the service log. The same text appears in apf-compile errors and in POST /v1/refresh responses.

ReasonDetail formatCauseFix
signature_invalidsignature_invalid: <detail>The signature did not verify. Refer to the next table. Nothing else is checked.Re-sign with a trusted key, and do not edit the signed file.
bundle_parse_failedbundle_parse_failed: <error>The signed payload is not a valid manifest.Fix the template and re-sign.
manifest_member_unreadablemanifest_member_unreadable: <manifest directory>/<path> (<error>)A member file is missing or unreadable.Ship every member, at its manifest path relative to the manifest.
manifest_hash_unsetmanifest_hash_unset: <path> (declared `<value>`)A digest is empty or still REPLACE_WITH_DIGEST.Sign with apf-compile genfixture.
manifest_hash_mismatchmanifest_hash_mismatch: <path>: declared <digest>, actual <digest>A member changed after signing.Re-sign, or restore the member.
not_before_invalidnot_before_invalid: <error>not_before is not RFC 3339.Fix the timestamp.
expires_at_invalidexpires_at_invalid: <error>expires_at is not RFC 3339.Fix the timestamp.
bundle_not_yet_validbundle_not_yet_valid: now <time> < not_before <time>The bundle is not valid yet.Wait, or check the host clock.
bundle_expiredbundle_expired: now <time> > expires_at <time>The bundle has expired.Publish a renewed bundle with a higher revision.
runtime_compat_invalidruntime_compat_invalid: <adapter>.min_version `<value>` is not semver (<error>)A min_version is not a semantic version.Fix the version string.
runtime_compat_mismatchruntime_compat_mismatch: bundle requires <adapter> >= <version>, caller is <version>Not produced in this release, because no runtime versions are supplied.
counter_regressioncounter_regression: bundle counter <n> <= high-water-mark <n>The revision is lower than the accepted one, or is 0.Publish with a higher revision.
counter_content_mismatchcounter_content_mismatch: bundle counter <n> already accepted with a different artifactDifferent content at the accepted revision.Increase policy_revision.

Signature Details

DetailCause
trust_root_unknown: <keyid> (loaded: [...])No trust root has the signature’s key ID.
cryptographic verification failedThe signed content changed, or the key does not match.
malformed or unsigned bundle artifactThe file has no valid signature document.
signature carrier has no keyidThe signature document lacks keyid.
artifact has no signing attemptThe file is not signed.
malformed signing attemptThe signature document is damaged.
unsupported algorithm <alg>The algorithm is not supported.

Policy Service Records

Activation

reason_codeoutcomeMeaning
policy.bundle_verifiedsuccessVerification passed. Recorded as policy_verification.
policy.bundle_loadedsuccessThe bundle verified, compiled, and its revision was recorded.
policy.no_projectionssuccessDefined for a startup bundle that produces no projections. Not expected in practice, because every bundle produces the policy set and provider profile set.
policy.bundle_hot_swappedsuccessAn HTTP source poll put a new bundle in force.
policy.bundle_rejected.counter_persist_failedrefusedThe counter store could not be written. The bundle is not activated. retryable is true. Check the counter store’s disk and permissions.
policy.bundle_rejected.counter_not_newerrefusedAn HTTP source poll fetched a bundle whose revision is not newer than the active one. It follows policy.bundle_verified and policy.bundle_loaded records for the same bundle. The active bundle stays.
policy.bundle_rejected.unspecifiedrefusedA policy_verification record. Verification failed with no recognizable reason. Read error.message.

A bundle that verifies but fails to load its members or compile produces no activation record. The refresh response or the service log carries the error, such as compile bundle: ....

Documents and Refresh

reason_codeoutcomeMeaning
policy.document_vendedsuccessA document was served. Recorded once per document and revision for each run of the service.
policy.document_not_foundrefusedNo document of that kind and name.
policy.document_request_invalidrefusedThe kind is empty or not in --surfaces.
policy.refresh_triggeredsuccessAn authenticated POST /v1/refresh arrived. A successful local refresh is then recorded as policy.bundle_loaded, and a verification failure as a refusal. A counter store write failure is recorded as policy.bundle_rejected.counter_persist_failed. Other failures write no further record: a missing bundle_path, an HTTP fetch failure, or a compilation error, which follows a successful policy.bundle_verified record.
policy.provenance_mint_failedfailureA provenance token could not be signed. The document was served without one, and the interceptor will deny admissions that use it.

Authentication

reason_codeMeaning
auth.http_bearer_invalidAn HTTP request to a protected route had a missing or wrong bearer token.
auth.uds_peer_rejectedA Unix socket peer’s UID did not match --allowed-uid.
auth.uds_peer_cred_failedA Unix socket peer’s credentials could not be read.
auth.uds_refusals_droppedRefusals arrived faster than they could be recorded. The record gives the count.

Gateway Records

reason_codeEvent typeMeaning
policy.bundle_activatedpolicy_activationThe gateway built its first evaluator at startup.
policy.bundle_hot_swappedpolicy_activationThe gateway swapped in a new evaluator.
policy.request_allowedauthorizationEvaluationService allowed a request.
policy.request_deniedauthorizationEvaluationService denied a request. error.message holds the deny reason.

If the gateway cannot fetch, decode, or build a new policy set, it logs get_document failed on hot-swap, PolicySet decode failed on hot-swap, or evaluator rebuild failed, keeps its current evaluator, and writes no record. At startup the same failures stop the gateway, with fetch apf.policy.v1 PolicySet, decode PolicySet, or build initial Cedar evaluator followed by the cause, for example build Cedar evaluator: evaluator engine error: rule '<name>': policy parse: ....

Interceptor Records

The interceptor answers OpenShell with allowed: false and the reason in the table. OpenShell refuses the operation.

Sandbox Creation

reason_codeReason returnedCause
interceptor.policy_injectedThe signed sandbox policy was injected.
interceptor.inject_denied.no_provenance_tokenpolicy service vended no provenance tokenThe policy service served the projection without a token.
interceptor.inject_denied.invalid_jwtprovenance JWT invalid, or a specific claim errorThe token’s signature, expiry, or claims failed. Check that --jwks-url points at the running policy service. The gateway fetches the key at startup and then every --jwks-refresh-interval-secs, so a policy service restarted with an ephemeral key invalidates tokens until the next fetch.
interceptor.inject_denied.policy_identity_mismatchresponse policy identity disagrees with the signed tokenThe served digest or version does not match the token.
interceptor.inject_denied.body_digest_mismatchpolicy body digest mismatchThe served body does not hash to the token’s digest.
interceptor.inject_denied.unsigned_projectionpolicy projection has no provenance tokenDefensive check. Not expected.
interceptor.validate_allowedValidation passed.
interceptor.validate_allowed.no_spec_digestValidation passed. The token carried no spec digest to compare.
interceptor.validate_denied.provenance_missingsandbox policy integrity check failedThe admission lost its provenance annotation.
interceptor.validate_denied.provenance_invalidsandbox policy integrity check failedThe provenance token or annotations do not verify.
interceptor.validate_denied.spec_digest_mismatchsandbox policy integrity check failedThe sandbox policy changed between injection and validation.

Infrastructure failures return a gRPC status instead and write no record: INVALID_ARGUMENT with operation missing name (sandbox_id), UNAVAILABLE with policy service unavailable: ..., or INTERNAL with patch generation failed: .... The last two also apply to configuration refreshes.

Configuration Changes

reason_codeReason returnedCause
interceptor.policy_injected.unverifiedThe current signed policy was injected into a configuration refresh.
No recordpolicy projection has no provenance tokenA refresh found no provenance token on the served projection.
interceptor.govern_denied.direct_policy_mutationdirect policy mutation not permitted; policy is managed by APFThe request tried to set the policy or merge operations directly.
interceptor.govern_denied.approval_mode_changeapproval mode is managed by APFThe request tried to change proposal_approval_mode.
interceptor.govern_denied.body_digest_mismatchpolicy body digest mismatchThe served body does not hash to its token’s digest.
interceptor.govern_denied.policy_identity_mismatchresponse policy identity disagrees with the tokenThe served digest or version does not match the token.
interceptor.validate_denied.post_injection_mutationconfig policy integrity check failedA forbidden field was added, or the policy removed, after injection.
interceptor.validate_denied.approval_mode_changeapproval mode is managed by APFThe validated request changes the approval mode.
interceptor.validate_denied.provenance_missing, interceptor.validate_denied.provenance_invalid, interceptor.validate_denied.spec_digest_mismatchconfig policy integrity check failedAs for sandbox creation.

Providers and Proposals

reason_codeReason returnedCause
interceptor.provider_type_allowedThe provider type is managed by the bundle.
interceptor.govern_denied.unmanaged_provider_typeprovider type '<type>' is not a bundle-managed profileCreate providers only of types the bundle defines.
interceptor.provider_profiles_allowedThe imported or updated profiles are managed by the bundle and match its content.
interceptor.govern_denied.unmanaged_provider_profileprovider profile '<id>' is not managed by the APF bundleAdd the profile to the bundle instead.
interceptor.govern_denied.profile_content_mismatchprovider profile '<id>' content does not match the APF bundleThe imported or updated profile differs from the bundle’s copy. Change the profile in the bundle, not in OpenShell.
interceptor.govern_denied.profile_deleteprovider profiles are bundle-managed; delete is not permittedRemove the profile from the bundle instead.
interceptor.govern_denied.policy_service_unavailable... governance check failed: policy service unavailableThe interceptor could not fetch the bundle’s profiles.
interceptor.policy_analysis_allowedA mechanistic policy analysis was allowed.
interceptor.govern_denied.agent_authored_proposalagent-authored policy proposals are not permitted; policy is managed by APFTurn off agent policy proposals in OpenShell.
interceptor.govern_denied.draft_approvalpolicy proposal approval is not permitted; policy is managed by APFChange policy through a bundle.

Other Interceptor RPCs

These return a gRPC status and write no record.

RPCStatusMessage
DescribeFAILED_PRECONDITIONOpenShell’s extension protocol metadata is missing or incompatible.
SnapshotProviderProfilesINTERNALlist_documents: ... or get_document '<name>': ...
SnapshotProviderProfilesFAILED_PRECONDITIONprovider profile verifier unavailable, provider profile provenance invalid, provider profile provenance mismatch, provider profile policy changed during snapshot, or provider profile snapshot contains an invalid profile

Middleware Records

The middleware returns a deny’s code to OpenShell without the middleware. prefix and records it with the prefix. An allow carries an empty code on the wire. middleware.allowed and middleware.allowed_with_findings appear only in audit records. A Describe protocol mismatch and WebSocket sessions return gRPC statuses, and a non-empty configuration makes ValidateConfig answer valid: false with configuration must be empty; received <n> field(s). None of these writes a decision record. Caller authentication failures on any RPC write extension_auth.* records.

reason_codeDecisionReason returnedCause
middleware.allowedAllowAllowed with no findings. The body or headers may have been rewritten.
middleware.allowed_with_findingsAllowAllowed with at least one finding.
middleware.policy_deniedDenyThe deny reasonThe policy denied the request.
middleware.evaluation_failedDenypolicy evaluation failedThe evaluator returned an error.
middleware.effect_application_failedDenypolicy effects could not be appliedA patch could not be applied, for example to a missing field or a body that is not JSON.
middleware.replacement_body_too_largeDenypolicy replacement body exceeds middleware limitThe rewritten body is over 4 MiB.
middleware.invalid_header_mutationDenypolicy produced an invalid header mutationA header mutation breaks the OpenShell header rules. Refer to Effects and Findings.
middleware.invalid_findingsDenypolicy produced invalid findingsMore than 32 findings, or one over 4 KiB.
middleware.invalid_mcp_requestDenyinvalid MCP tools/call requestA malformed tools/call, or a JSON-RPC batch that contains one.
middleware.body_too_largeDenyrequest body exceeds middleware limitThe request body is over 4 MiB.
middleware.missing_targetDenyHTTP request target is missingOpenShell sent no target.
middleware.invalid_phaseDenyunsupported middleware phaseThe call was not at PRE_CREDENTIALS. Check the OpenShell registration.
middleware.invalid_configDenymiddleware configuration must be emptyThe sandbox policy’s middleware entry carries a config.

Authentication Records

Written by the interceptor and middleware to their own audit files. Not written in insecure mode.

reason_codegRPC statusCause
extension_auth.credential_invalidUNAUTHENTICATEDThe bearer JWT is missing, malformed, expired, or does not match the trust profile.
extension_auth.caller_unauthenticatedUNAUTHENTICATEDNo authenticated caller on the request.
extension_auth.caller_not_allowedPERMISSION_DENIEDA gateway or supervisor called an RPC it may not call.
extension_auth.sandbox_binding_mismatchPERMISSION_DENIEDA supervisor’s token is bound to a different sandbox than the request. Middleware only.

Deny Reasons

The policy’s deny reason appears as reason on a middleware deny, in error.message on its audit record, and as reason from EvaluationService.

FormatCause
<rule>/<id>A forbid fired in <rule>. <id> is its @id annotation, or a Cedar policy ID such as policy1 without one.
<id>A forbid with an @id that already contains /, such as security-content-gate/deny-secret.
no grant for <action>A tool call that no capability grant permits. <action> is the tool name, or <tool>::<capability> from an EvaluationService call that sends a verb.
<rule>: conditions not met for <action>A tool call that no grant permits, where a capability rule named after the tool exists.
runtime_error:missing_annotation_source:<path>An effect or finding reads an annotation the request did not produce.
pip_<status>:<provider>A policy information provider registered with on_failure: fail_closed could not answer. <status> is the lookup status, such as timeout or unavailable, and <provider> is the registered name. pip_invalid_input denies regardless of the failure mode. Refer to Policy Information Providers.

gRPC Status Codes

The policy service’s PolicyService and the gateway’s EvaluationService return these statuses. Refer to Service APIs for details.

Service and RPCStatusMessage
PolicyService GetDocument, ListDocumentsINVALID_ARGUMENTkind must be non-empty, or kind '<kind>' is not served by this instance
PolicyService GetDocumentNOT_FOUNDdocument '<kind>/<name>' not found
EvaluationService EvaluateINTERNALevaluator engine error: <detail>. No audit record is written.

Policy Service HTTP Status Codes

StatusBodyCause
400kind must be non-empty or kind '<kind>' is not served by this instanceEmpty or unserved kind.
400, 422Generated by the HTTP frameworkA POST /v1/refresh JSON body that is malformed, empty, or has the wrong shape. No audit record is written.
415Generated by the HTTP frameworkA POST /v1/refresh body with a Content-Type other than JSON. curl -d without a JSON header sends form encoding and gets this. A request with no Content-Type is treated as having no body.
405Generated by the HTTP frameworkThe wrong method for a route.
401missing or invalid bearer tokenBad or missing token.
404document '<kind>/<name>' not foundUnknown document.
500refresh failed: <error>A local source refresh failed, for example bundle_path is required for local bundle refresh, bundle verification failed: [...], or counter advance: .... An HTTP source refresh does not return 500.
503{"status":"not_ready","reason":"no bundle loaded"}/readyz before a bundle is active.

Next Steps