Windows: thread/start fails with os error 206 ("failed to load AGENTS.md instructions") - deny-read glob expansion overflows the sandbox helper command line
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What version of the Codex App are you using (From "About Codex" dialog)?
Codex App 26.825.6671.0 (MSIX), app-server client_version 26.825.51511, codex-rs client_version 0.151.0 (from logs_2.sqlite).
What subscription do you have?
ChatGPT workspace account with enterprise-managed Codex policies (cloud-delivered requirements bundle).
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64 (Windows 11 Pro). HKLM\...\FileSystem\LongPathsEnabled = 0 (note: not the cause — see analysis; the 32,767-char command-line limit applies regardless).
What issue are you seeing?
Every attempt to start a new chat on environment local fails after a ~40 s stall with:
Error creating chat
error creating thread: Fatal error: Failed to initialize session: failed to load AGENTS.md instructions for environmentlocal: The filename or extension is too long. (os error 206)
From ~/.codex/logs_2.sqlite (redacted):
[ERROR] codex_core::session core\src\session\mod.rs:791
app_server.request{... rpc.method="thread/start" ... app_server.client_version="26.825.51511"}
:app_server.thread_start.create_thread{...}:thread_spawn{...}:
Failed to create session: failed to load AGENTS.md instructions for environment `local`:
The filename or extension is too long. (os error 206)
Reproduces on 100% of thread starts on this machine (two consecutive attempts logged identically, ~42 s and ~26 s after session_init). The project folder is a freshly auto-created, empty Documents\Codex\<date>\<slug> directory — the failure is unrelated to project contents.
What steps can reproduce the bug?
Preconditions:
- Windows 11 machine with a normally-used Chrome profile (tens of thousands of files under
%LOCALAPPDATA%\Google\Chrome). - Enterprise-managed requirements that (a) allow only a restricted managed permission profile (no full-disk read, so
:root = "deny"), (b) use the elevated Windows sandbox ([windows] sandbox = "elevated"), and (c) contain recursive deny-read globs over large directory trees. Minimal example:
default_permissions = "managed_net"
[allowed_permission_profiles]
managed_net = true
[permissions.managed_net]
extends = ":workspace"
[permissions.managed_net.filesystem]
glob_scan_max_depth = 8
":root" = "deny"
":minimal" = "read"
[permissions.filesystem]
deny_read = [
"~/AppData/Local/Google/Chrome/**",
]
Steps:
- Open the Codex App, start any new chat on environment
local(an empty project folder suffices). - Wait ~40 s → the "Error creating chat … os error 206" failure above.
What is the expected behavior?
The session starts and the deny-read policy is enforced. Whether the sandbox helper can be spawned should not depend on how many pre-existing files happen to match a deny glob on the host. Ideally an AGENTS.md discovery failure would also not hard-fail thread creation (or at least produce an actionable error instead of a raw OS error).
Additional information
Root-cause analysis against codex-rs @ a9519cb (current main; the failing code paths match the shipped app's behavior and log lines):
thread/start→ session init loads AGENTS.md instructions. Under a managed profile without full disk read access, discovery runs through the sandboxed filesystem, and — unlike the default profiles where discovery errors are only logged — any error is fatal to session creation:core/src/agents_md.rs#L94-L108. This is why only enterprise-managed installs surface this as "can't create any chat".- Each sandboxed FS operation (even the
get_metadataprobes forAGENTS.md) spawns a sandboxed helper process:exec-server/src/sandboxed_file_system.rs#L193-L221→exec-server/src/fs_sandbox.rs#L75-L121. - The Windows direct-spawn transform resolves filesystem overrides for the elevated backend:
sandboxing/src/manager.rs#L572-L627→sandboxing/src/windows.rs#L213-L242. - Because Windows ACLs can't express globs, every deny-read glob is snapshot-expanded into concrete matching paths by scanning the filesystem (ripgrep or the fallback walker, capped by
glob_scan_max_depth):windows-sandbox-rs/src/deny_read_resolver.rs#L31-L98. This scan is the ~40 s stall. - The full expanded path list is JSON-serialized into a single command-line argument for the sandbox wrapper:
windows-sandbox-rs/src/wrapper.rs#L105-L111(DENY_READ_PATHS_JSON_FLAG), alongside the serialized permission profile and env JSON. - Windows caps a
CreateProcessWcommand line at 32,767 UTF-16 chars. When the expansion is large,Command::spawnfails withERROR_FILENAME_EXCED_RANGE= "The filename or extension is too long. (os error 206)". That raw error is stringified atexec-server/src/fs_sandbox.rs#L484-L489, travels back as the JSON-RPC error message, and is re-wrapped once byagents_md.rs— producing exactly the observed message. (The alternative error sites in this path — walker abort, ripgrep failure, transform errors — all wrap the message with prefixes likefailed to enumerate unreadable glob paths under …; the observed error has no such prefix, so the bare os error can only come from the helper spawn.)
Measured on the affected machine (items within glob_scan_max_depth = 8, full-path character totals):
| deny glob target | items | path chars |
|---|---|---|
~/AppData/Local/Google/Chrome/** |
23,603 | 3,573,708 |
~/.docker/** |
4,363 | 395,906 |
~/AppData/Roaming/Mozilla/Firefox/** |
2,292 | 371,747 |
~/.kube/** |
2,148 | 242,446 |
JSON-escaped (backslashes doubled, quotes and commas added) that is roughly 4.8 MB in one argv element vs. the 32,767-char limit — >100× over. Session creation can never succeed on such hosts, and any sandboxed command would hit the same wall even if AGENTS.md discovery were skipped.
Related hazards spotted in the same area:
- The elevated setup/refresh path has the same ceiling: the whole
ElevationPayload(includingdeny_read_paths) is base64-encoded into a single argument inwindows-sandbox-rs/src/setup.rs#L322-L375. - With ripgrep unavailable, the fallback walker aborts the whole snapshot on any unexpected I/O error, including path-too-long (error 206) on
LongPathsEnabled=0hosts:windows-sandbox-rs/src/deny_read_walker.rs#L131-L147. - Possibly the same scale problem underlies other Windows deny-read ACL reports (#36087, #32525, #30758 — different symptom, same subsystem).
Potential approaches to a fix (per the contributing guide, offered as analysis rather than a PR):
- Transport: pass the large JSON payloads (deny paths, permission profile, env) to the wrapper via stdin or a temp file instead of argv; same for the elevated setup payload (a short file path survives ShellExecute/UAC where stdin cannot).
- Scale: don't enumerate beneath a directory that is already deny-matched — an inherited deny ACE on the directory covers the subtree, so descendants in the snapshot are redundant. A
dir/**glob could short-circuit to its literal root without scanning at all, which would also remove the ~40 s per-session scan. - Resilience: consider degrading AGENTS.md discovery failures to a warning under sandboxed profiles too, or at least attaching context (which operation/paths) to the fatal error instead of a bare OS error.
Admin workaround that restores service immediately: in managed policies, use exact directory paths (no trailing /**) for directory-shaped deny-read entries, e.g. "~/AppData/Local/Google/Chrome" instead of "~/AppData/Local/Google/Chrome/**" — exact roots are passed through without expansion (deny_read_resolver.rs#L24-L40) and a directory deny covers its subtree. Verified working on the affected machine.
🤖 Root-cause analysis generated from local ~/.codex logs and codex-rs sources @ a9519cb.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with windows-sandbox-rs/src/deny_read_resolver.rs and wrapper.rs, then trace the payload through sandboxing/src/windows.rs and exec-server/src/fs_sandbox.rs. Reproduce with the managed profile and a large recursive deny-read glob. Done means Windows session and sandbox-helper startup no longer fail with os error 206 while the deny-read policy remains enforced.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- devtools, operating-systems, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100