openai/codex · error · std::io::Error

`approval_policy = "never"` cannot be used because requireme

Error message

`approval_policy = "never"` cannot be used because requirements do not allow `sandbox_mode = "danger-full-access"`; Codex would fall back to read-only permissions with approvals disabled. Choose an `approval_policy` based on what you need, such as `on-request`, or choose an allowed sandbox mode.

What it means

Managed requirements can constrain the permission profile. If the selected profile demands sandbox_mode = "danger-full-access", requirements forbid it, and the constrained profile falls back to read-only while the effective approval policy is Never, Codex would run read-only with approvals disabled: able neither to write nor to ask. Config::load refuses to start and directs you to a workable approval policy or an allowed sandbox mode.

Source

Thrown at codex-rs/core/src/config/mod.rs:3975

        apply_requirement_constrained_value(
            "approvals_reviewer",
            approvals_reviewer,
            &mut constrained_approvals_reviewer,
            &mut startup_warnings,
        )?;
        let permission_profile_was_constrained = apply_requirement_constrained_value(
            "permission_profile",
            permission_profile,
            &mut constrained_permission_profile,
            &mut startup_warnings,
        )?;
        if permission_profile_was_constrained
            && sandbox_mode_requirement_for_permission_profile(&original_permission_profile)
                == SandboxModeRequirement::DangerFullAccess
            && constrained_permission_profile.get() == &PermissionProfile::read_only()
            && constrained_approval_policy.value() == AskForApproval::Never
        {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                "`approval_policy = \"never\"` cannot be used because requirements do not allow `sandbox_mode = \"danger-full-access\"`; Codex would fall back to read-only permissions with approvals disabled. Choose an `approval_policy` based on what you need, such as `on-request`, or choose an allowed sandbox mode.",
            ));
        }
        if permission_profile_was_constrained {
            // The selected profile no longer describes the effective
            // permissions after requirements forced a fallback.
            active_permission_profile = None;
            profile_workspace_roots.clear();
        }
        apply_requirement_constrained_value(
            "web_search_mode",
            web_search_mode,
            &mut constrained_web_search_mode,
            &mut startup_warnings,
        )?;

        let mcp_servers = constrain_mcp_servers(cfg.mcp_servers.clone(), mcp_servers.as_ref())

View on GitHub (pinned to 339751715c)

Solutions

  1. Set `approval_policy = "on-request"` (or "on-failure") so escalation is still possible under the constrained profile.
  2. Or select a permission profile whose sandbox mode the requirements allow (e.g. workspace-write), avoiding the read-only fallback.
  3. Or have the requirements owner allow the needed sandbox mode for this workflow.
  4. Also drop any override forcing Never (e.g. a bypass-approvals override) so the pairing cannot occur.

Example fix

# before - never-approve paired with a full-access profile
approval_policy = "never"
default_permissions = "full-access-profile-id"

# after - approvals available under an allowed profile
approval_policy = "on-request"
default_permissions = "workspace-write-profile-id"
Defensive patterns

Strategy: validation

Validate before calling

# Pre-flight: never combine approval_policy=never with a profile
# that requirements will constrain to read-only
import tomllib
cfg = tomllib.load(open("config.toml", "rb"))
never = cfg.get("approval_policy") == "never"
full_access = cfg.get("default_permissions") in FULL_ACCESS_PROFILE_IDS  # ids requiring danger-full-access
if never and full_access and requirements_deny_danger_full_access():
    raise SystemExit("pick on-request or an allowed profile")

Try / catch

match config_result {
    Err(ref e) if e.kind() == std::io::ErrorKind::InvalidInput
        && e.to_string().contains("requirements do not allow") => {
        // fall back to approval_policy = on-request and retry config load
    }
    other => other,
}

Prevention

When it happens

Trigger: A requirements layer (e.g. enterprise-managed config) that disallows danger-full-access, combined with a permission profile requiring danger-full-access and an effective approval_policy of "never" (explicit or resolved via override). Fires only when the profile was actually constrained down to read-only.

Common situations: Corporate-managed Codex installs where users copy their personal full-trust config (never-approve plus full access); CI automation configs reused across environments with stricter requirements; bypass-style flags colliding with managed policy.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/a6b07e086ffd53ca. Report an issue: GitHub.