Restricted permission profile + AGENTS.md in workspace makes session start fail with misleading "sessions corrupt" error

Open 💬 3 comments Opened Aug 26, 2026 by kelp
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

codex-cli 0.149.1 (root cause confirmed against main at 7625bd5665)

What subscription do you have?

Teams

Which model were you using?

gpt-5.6-sol (not relevant; the failure happens before the first turn)

What platform is your computer?

macOS 15 (Darwin 25.6.0), Apple Silicon

What terminal emulator and version are you using (if applicable)?

n/a — reproduces headless with codex exec

Codex doctor report

(omitted; can attach on request)

What issue are you seeing?

With a custom permission profile whose read access does not cover the working directory, starting a session in any directory that contains an AGENTS.md fails before the first turn:

Error: thread/start failed: error creating thread: Fatal error: Session data under
/Users/me/.codex/sessions looks corrupt or unreadable. Clearing the sessions directory
may help (this will remove saved threads). (underlying error: failed to load AGENTS.md
instructions for environment `local`: Operation not permitted (os error 1)) (code -32603)

The sessions directory is fine. The real failure is the sandboxed AGENTS.md read, and the error text steers users toward deleting their saved threads for no benefit.

What steps can reproduce the bug?

~/.codex/config.toml:

default_permissions = "code-write"

[permissions.code-write.filesystem]
":minimal" = "read"
"/Users/me/code" = "write"
mkdir -p /Users/me/src/project && cd /Users/me/src/project   # outside the profile's roots
echo "# instructions" > AGENTS.md
codex exec "say hi"    # fails as above

Controls, each of which starts fine:

  • Same directory without AGENTS.md (a missing file is tolerated; only present-but-unreadable is fatal).
  • Same setup in a directory under /Users/me/code.

What is the expected behavior?

Ideally the session starts and AGENTS.md is skipped with a warning that the sandbox denied the read. If fail-closed is the intended policy (per #39653, "Fail thread or turn setup when sandboxing blocks a discovered instruction file"), the error should say the permission profile blocked reading <path>/AGENTS.md and name the profile — not claim the sessions directory is corrupt.

Additional information

  • Introduced by #39653 ("Enforce filesystem permissions when loading AGENTS.md"), first shipped in rust-v0.149.0; not present in rust-v0.148.0.
  • Root cause: in codex-rs/core/src/agents_md.rs, load_project_instructions logs the error when no sandbox context applies but returns it (fatal to thread start) when the profile lacks full disk read. The "corrupt or unreadable" wrapper comes from session_rollout_init_error.rs, which applies that hint to any thread-creation error.
  • #40245 appears to be the same defect on Windows (custom profile + non-empty AGENTS.md, task creation fails with os error 206). Its bot-suggested duplicate #38985 is an unrelated command-line-length bug.
  • Workarounds, both verified or reported: add the workspace to the profile's filesystem roots (verified on macOS); project_doc_max_bytes = 0 (reported in #40245).

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 1 day ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #40245

Powered by Codex Action

kelp · 1 day ago

Not a duplicate to close: #40245 is the Windows manifestation of the same core defect, referenced in this report. This issue adds the macOS reproduction, the root cause (load_project_instructions in codex-rs/core/src/agents_md.rs makes a sandbox-denied AGENTS.md read fatal to thread start; introduced in #39653, first shipped in rust-v0.149.0), and the misleading "sessions corrupt" wrapper from session_rollout_init_error.rs. Keeping both open and cross-linked until a maintainer decides where to consolidate.

kelp · 1 day ago

Proposed fix, two independent parts.

1. Behavior: skip-with-warning instead of failing thread start (codex-rs/core/src/agents_md.rs, in load_project_instructions). The security goal of #39653 — instructions the profile cannot read must never reach the model — is preserved by skipping, since nothing is loaded. Merging the two Err arms makes the sandboxed path degrade the same way the unsandboxed path already does:

             Ok(None) => {}
-            Err(error) if sandbox.is_none() => {
+            Err(error) => {
                 error!(
                     environment_id = turn_environment.selection.environment_id,
                     "error trying to find AGENTS.md docs: {error:#}"
                 );
             }
-            Err(error) => {
-                return Err(io::Error::new(
-                    error.kind(),
-                    format!(
-                        "failed to load AGENTS.md instructions for environment `{}`: {error}",
-                        turn_environment.selection.environment_id
-                    ),
-                ));
-            }
         }

Ideally this also surfaces a user-visible warning (not just tracing) so users know their instructions were skipped, e.g. "Permission profile code-write denies reading AGENTS.md at <path>; grant the workspace read access or set project_doc_max_bytes = 0."

2. Error attribution: stop blaming the sessions directory. map_session_init_error in codex-rs/core/src/session_rollout_init_error.rs downcasts any io::Error in the chain and maps it to a sessions-directory hint. The sandbox denial arrives with kind InvalidData (the exec-server transport re-wraps the EPERM), so it hits the "Session data ... looks corrupt or unreadable. Clearing the sessions directory may help" branch — advice that would cost users their saved threads for nothing. Even if part 1 is rejected and fail-closed stays, map_rollout_io_error should only match errors that actually originate from rollout/session storage (e.g. a dedicated error type or a marker in the chain), and an AGENTS.md load failure should produce its own message naming the blocked path and the active permission profile.

Happy to send a PR for either or both.