Breaking config change: `:project_roots` no longer works in recent Codex releases

Open 💬 2 comments Opened May 21, 2026 by RyanMentley

What version of Codex CLI is running?

codex-cli 0.132.0

What subscription do you have?

Business

Which model were you using?

gpt-5.4

What platform is your computer?

Darwin 25.4.0 arm64 arm

What issue are you seeing?

A recent Codex release appears to have made a breaking change to the config permission token for project-scoped filesystem access.

Previously, configs and docs used :project_roots, but recent Codex behavior now rejects that token and expects :workspace_roots instead.

Observed behavior

The Codex TUI warns:

Configured filesystem path `:project_roots` is not recognized by this version of Codex and will be ignored.

The desktop app does not seem to warn at all.

In either case, the intended project-root write access is not granted.

What steps can reproduce the bug?

A config like this no longer works in current releases:

[permissions.default-dev.filesystem]
":project_roots" = "write"

What is the expected behavior?

This should not have been a breaking config change without a compatibility path.

At minimum, one of these should happen:

  1. Preserve :project_roots as a supported alias for backward compatibility.
  2. Emit a direct migration error/warning that explicitly says to replace :project_roots with :workspace_roots.
  3. Call out the breaking change prominently in release notes and migration guidance.

Additional information

Why this matters
This can break existing Codex setups that were previously valid. A config may continue to load, but the relevant filesystem permission is ignored, leading to unrelated-looking failures later when commands no longer have the expected project-root access.

Because the old key is ignored rather than rejected with a clear migration message, this is harder to understand than it should be.

Related context

  • PR #22624 renamed the config-facing key from :project_roots to :workspace_roots.
  • Current docs now appear to match the new behavior, but that still leaves existing user configs broken.

Suggested resolution

  • Restore :project_roots as a compatibility alias, or
  • add an explicit migration diagnostic that names :workspace_roots as the replacement, and
  • document the breaking change prominently for users upgrading Codex.

View original on GitHub ↗

2 Comments

jshaofa-ui · 3 months ago

Proposed Solution: :project_roots Backward Compatibility

Root Cause

PR #22624 renamed :project_roots to :workspace_roots without adding a backward-compatibility alias or migration warning. The config parser silently ignores the old token, causing project-root write access to be lost.

Fix

  1. Add backward-compatibility alias: Map :project_roots to the same resolution as :workspace_roots
  2. Add migration warning: Emit a clear deprecation warning that names the replacement token
  3. Auto-migrate: Automatically replace deprecated tokens with a logged warning

Key Code Change

pub fn resolve_token(token: &str, workspace: &Workspace) -> Option<PathBuf> {
    match token {
        ":workspace_roots" => workspace.roots.first().cloned(),
        ":project_roots" => workspace.roots.first().cloned(),  // Alias
        ":cwd" => Some(workspace.cwd.clone()),
        _ => None,
    }
}

Full solution: solutions/codex-23826-project-roots-config-breaking-change-fix.md

RyanMentley · 3 months ago

Note that #22624 contains a mistaken assertion[^1] regarding whether :project_roots was shipped publicly:

[...]:project_roots and :danger-no-sandbox have not shipped as stable user-facing surface area[...]

This is incorrect, at least regarding the documentation[^2]. I happened to have a tab open to https://developers.openai.com/codex/config-reference from before this change, showing this publicly documented key with no indication of experimental or otherwise pre-stable status:

<img width="1754" height="386" alt="Image" src="https://github.com/user-attachments/assets/a05ab34d-7721-47c8-a3d2-ef6754c74e23" />

Text version for accessibility:

Key | Type / Values | Details
-- | -- | --
permissions.<name>.filesystem | table | Named filesystem permission profile. Each key is an absolute path or special token such as :minimal or :project_roots.
permissions.<name>.filesystem.":project_roots".<subpath-or-glob> | "read" \| "write" \| "none" | Scoped filesystem access relative to the detected project roots. Use "." for the root itself; glob subpaths such as "**/*.env" can deny reads with "none".

[^1]: This mistaken assumption likely caused this correct review comment flagging the problem to go unaddressed.

[^2]: I'm not able to say with certainty whether the behavior itself was previously working, as I was configuring the sandbox, working through issues, and had not yet completed testing of the full setup.