Skip to content
Ironflow is pre-1.0: APIs can change between releases. Pin a version. What is ready →

Policy set errors

Every 4xx and 503 answer of the policy-set routes carries a machine-readable code. The SDKs expose the codes as POLICY_SET_ERROR_CODES (JavaScript) and as PolicySetErr* constants (Go).

An error body has this shape:

{
"error": "policy_set_builtin_forbidden: authz.rego:7:3: builtin http.send is not allowed in a policy set",
"message": "policy_set_builtin_forbidden: authz.rego:7:3: builtin http.send is not allowed in a policy set",
"code": "policy_set_builtin_forbidden",
"details": { "errors": [ { "file": "authz.rego", "line": 7, "col": 3, "message": "builtin http.send is not allowed in a policy set" } ] },
"retryable": false
}

A validation error (HTTP 400) lists one entry in details.errors for each problem. An entry has file, line, col and message. A problem that is not in one file has only message. One failure rejects the whole set.

These codes come from PUT, rollback, validate and dry-run with a candidate set.

CodeCauseFix
policy_set_compile_errorA file does not parse as Rego, or the set does not compile (unknown function, unsafe variable, recursion). The compiler may also have failed with an internal error.Read details.errors for the file and line. Run opa check locally.
policy_set_v0_syntaxA file uses Rego v0 syntax. Ironflow reads Rego v1 only.Run opa fmt --v0-v1 -w <dir>. The command changes the syntax and keeps the logic.
policy_set_reserved_namespaceA file declares a package under data.ironflow, other than ironflow.authz or ironflow.authz_test.Use package ironflow.authz for the entry point, or a package outside ironflow.
policy_set_builtin_forbiddenA file calls or references a banned builtin: http.send, net.lookup_ip_addr, opa.runtime, json.match_schema, json.verify_schema, bits.lsh, regex.replace, regex.split, regex.find_n, regex.find_all_string_submatch_n, regex.template_match or indexof_n.Remove the call. See Author a policy set.
policy_set_sprintf_formatThe first argument of sprintf is not a string literal, has a * width, has a width or precision above 9999, or has more than 32 verbs. sprintf is also not allowed as a with value.Write the format as a literal within the limits.
policy_set_schema_errorA rule in package ironflow.authz does not type-check against the input schema.Fix the field name or type at the given line.
policy_set_entrypoint_typedeny is not a partial set rule, or the decision rule is a set or a function, or its type is not a boolean or an object.Write deny contains <reason> if { ... }. Write the decision rule as a complete rule, for example allow := ....
policy_set_bad_file_nameA file name is not a relative path of [A-Za-z0-9_.-] segments that ends in .rego, has a . or .. segment, is in a .ironflow or .git directory, or differs only in case from another name.Rename the file.
policy_set_too_largeThe set has more than 500 files, or more than 2 MiB of source. With HTTP 413, the request body is larger than the limit.Remove files or split the work.
policy_set_compile_timeoutCompiling the set took longer than 2 seconds.Simplify the set. Remove very large generated files.
policy_set_bad_modeThe mode is not enforce or monitor.Use one of the two values, or omit the field.
policy_set_bad_decisionThe decision path is not a rule path under data outside data.ironflow, or the rule is not defined.Name an existing rule, for example data.envoy.authz.allow.
policy_set_bad_requestThe request is malformed: invalid JSON, an unknown field, invalid UTF-8, an If-Match value that is not a version number, a version in the path that is not a positive integer, or a dry-run input without request and subject objects.Fix the request.
CodeHTTPCauseFix
policy_set_forbidden403A platform route was called without platform credentials, or a tenant route was called without an organization. The platform set is not reachable through the tenant routes.Use platform credentials for /api/v1/platform/policy-set.
policy_set_not_found404The version does not exist, the organization has no set for a dry-run of the active set, or the organization was not found (force-monitor).List the versions. Send set in the dry-run to test a candidate.
policy_set_version_conflict412If-Match does not match the active version. Another admin wrote first.Run ironflow policy pull, merge your changes and push again.
policy_set_precondition_required428A PUT or rollback has no If-Match header.Send the version that you read (0 when the organization has no set). The header accepts 3, "3" and W/"3".
policy_set_self_lockout422 or 503The preflight found that the candidate set would deny a subject who must keep write access, or it could not decide. The body names blocking_subject, reason and detail. A store failure or a timeout answers 503, which you can retry.Fix the rules. As a last step, use the bypass. See Recover from a lockout.
policy_set_rate_limited429The organization wrote too fast (one write every 6 seconds, burst 5), or called validate or dry-run too fast (one call every second, burst 10). The limits apply to each node.Wait for Retry-After seconds.
policy_set_busy429Four compiles are already running on this node.Retry after one second.
policy_set_not_propagated503The write committed, but this node could not finish adopting it. Other nodes may still use the old set. The error is not retryable.See below.

The message says saved as version N but not yet active on every node; send the same request again with If-Match: N (a no-op that finishes propagation).

The write is stored as version N. Do not resend with the old version, because that answers 412. Send the same request again with If-Match: N. The server sees that the set is unchanged and finishes propagation. The CLI records N in .ironflow-policy.json and tells you to run the same command again. The SDKs mark the error as not retryable, so a retry loop does not resend it with the old version.

The same recovery applies to a rollback and to force-monitor.

The body of policy_set_self_lockout has an error field with one of two values:

errorHTTPMeaning
self_lockout_preflight_failed422The candidate set denies the named subject a read or write action on the policy set (GET or PUT /api/v1/policy-set, or GET /api/v1/policy-set/versions).
self_lockout_preflight_indeterminate422 or 503The preflight could not decide. A store failure, or one evaluation that timed out, is 503. A set that fails to evaluate, or a budget that ran out (10,000 evaluations or one second of evaluation), is 422.

These are not API errors. They appear as audit reasons. See Debug a deny.

Audit reasonMeaning
policy evaluation error (builtin_error)A builtin failed.
policy evaluation error (conflict)A complete rule produced two values.
policy evaluation error (timeout)The set ran longer than 50 ms.
policy evaluation error (panic)The evaluator failed with a panic.
policy evaluation error (eval_error)Another evaluation error.
policy evaluation error (compile_error)The stored set does not compile on this node.
policy evaluation error (load_error)The node could not read the set from the store.
non-string deny reasonA deny member was not a string.