openai/codex · error

approval_policy = "untrusted" is no longer supported; remove

Error message

approval_policy = "untrusted" is no longer supported; remove this setting

What it means

Part of post-consolidation validation: tokio::fs::metadata follows links, so the ensure! fires when MEMORY.md exists but is not a regular file — typically a directory or a symlink to one (codex-rs/memories/write/src/workspace.rs:65). The validator refuses to bless a tree whose primary memory artifact has the wrong file type; the read itself is wrapped with a 'read consolidated memory artifact' context.

Source

Thrown at codex-rs/app-server/src/config_manager_service.rs:741

            for item in items {
                array.push(toml_value_to_value(item)?);
            }
            Ok(toml_edit::Value::Array(array))
        }
        TomlValue::Table(table) => {
            let mut inline = toml_edit::InlineTable::new();
            for (key, val) in table {
                inline.insert(key, toml_value_to_value(val)?);
            }
            Ok(toml_edit::Value::InlineTable(inline))
        }
    }
}

fn validate_config(value: &TomlValue) -> anyhow::Result<()> {
    let config: ConfigToml = value.clone().try_into()?;
    if config.approval_policy == Some(AskForApproval::UnlessTrusted) {
        anyhow::bail!(
            "approval_policy = \"untrusted\" is no longer supported; remove this setting"
        );
    }
    Ok(())
}

fn paths_match(expected: impl AsRef<Path>, provided: impl AsRef<Path>) -> bool {
    path_utils::paths_match_after_normalization(expected, provided)
}

fn value_at_path<'a>(root: &'a TomlValue, segments: &[String]) -> Option<&'a TomlValue> {
    let mut current = root;
    for segment in segments {
        match current {
            TomlValue::Table(table) => {
                current = table.get(segment)?;
            }
            TomlValue::Array(items) => {

View on GitHub (pinned to 339751715c)

Solutions

  1. Inspect the entry (ls -l <root>/MEMORY.md) and remove the offending directory or link.
  2. Re-run consolidation so MEMORY.md is regenerated as a regular file.
  3. Exclude the memories root from tools that convert files into directories or links.

Example fix

# before
~/.codex/memories/MEMORY.md/   # accidentally a directory
# after
rm -r ~/.codex/memories/MEMORY.md && codex memories consolidate
Defensive patterns

Strategy: validation

Validate before calling

async fn memory_md_is_file(root: &std::path::Path) -> bool {
    tokio::fs::metadata(root.join("MEMORY.md"))
        .await
        .map(|m| m.is_file())
        .unwrap_or(false)
}

Try / catch

if let Err(e) = validate_consolidation_artifacts(root).await {
    if e.to_string().contains("is not a file") {
        // remove the offending directory/symlink at MEMORY.md and re-run
        // consolidation so the artifact is regenerated
    }
}

Prevention

When it happens

Trigger: After consolidation, root/MEMORY.md is a directory, a symlink to a directory, or another non-file entry (fifo, mount point).

Common situations: MEMORY.md replaced by a folder by sync/merge tools; symlinked from a dotfiles repo; partial merges leaving a directory where the file belongs.

Related errors


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