Skip to content

Windows: NUL-filled .sandbox/deny_read_acl_state.json permanently breaks sandbox setup and survives reinstall ("Windows setup didn't finish") #35718

Description

@Sentinel-Bluebuilder

Summary

A single zero-byte-filled state file permanently breaks Codex sandbox setup, and the failure survives a full uninstall/reinstall because the file lives in CODEX_HOME rather than in the app package. The app then shows the "Finish Windows setup" screen with "Windows setup didn't finish" on every launch, and "Try Windows setup again" fails instantly without ever raising a real UAC prompt.

The underlying trigger is an unclean shutdown (power loss / hard reset) while Codex is running. NTFS records the file's allocated size but never flushes its contents, so on reboot the file exists at its original length and is filled entirely with NUL (0x00) bytes. The JSON/TOML parsers then fail at the first byte.

This appears to be the actual root cause behind several existing reports that were attributed to Windows Home / Windows Sandbox availability, e.g. #28566 and #32492.

Root cause

codex-windows-sandbox-setup.exe reads <CODEX_HOME>/.sandbox/deny_read_acl_state.json unconditionally at startup. When that file is NUL-filled, setup aborts:

setup error: apply deny-read ACLs

Caused by:
    0: parse deny-read ACL state <CODEX_HOME>\.sandbox\deny_read_acl_state.json
    1: expected value at line 1 column 1
setup refresh: exited with status ExitStatus(ExitStatus(1))

expected value at line 1 column 1 is the parser hitting 0x00 as the first byte.

Setup then writes .sandbox/setup_error.json, which persists the failed state so the "setup didn't finish" screen reappears on every subsequent launch — even after the corrupt file itself would otherwise be harmless.

<CODEX_HOME>/config.toml was corrupted the same way in the same event (correct file size, 100% NUL bytes), which independently prevents config load.

Why reinstalling does not help

Remove-AppxPackage removes the package but leaves both CODEX_HOME and the app's per-user LocalCache/LocalState intact. The corrupt state is re-read immediately by the fresh install, so the user sees an identical failure and reasonably concludes the app itself is broken.

Environment

  • Windows 11 Home Single Language, build 10.0.26200 (x64)
  • ChatGPT/Codex desktop app 26.721.4979.0 (also reproduced on 26.715.4045.0)
  • Sandbox marker version: 5; CodexSandboxOffline / CodexSandboxOnline users present and enabled
  • WebView2 Runtime 150.0.4078.99, intact
  • UAC enabled (EnableLUA = 1), user is a local administrator

Worth noting: Windows Sandbox is not the issue here. That optional feature is unavailable on Home SKUs by design, and Codex's own ACL/restricted-token sandbox does not require it. Setup fails purely on the unparseable state file.

Steps to reproduce

  1. Run the Codex desktop app normally so .sandbox/deny_read_acl_state.json exists.
  2. Hard-power-off the machine while the app is running (or simulate: overwrite the file with NUL bytes of the same length).
  3. Boot and launch the app.

Expected: setup detects the unreadable state file, discards it, and regenerates a default.
Actual: setup aborts; "Windows setup didn't finish" appears on every launch; "Try Windows setup again" fails instantly; reinstalling does not clear it.

Minimal simulation of the corrupt state:

$p = "$env:USERPROFILE\.codex\.sandbox\deny_read_acl_state.json"
[System.IO.File]::WriteAllBytes($p, (New-Object byte[] (Get-Item $p).Length))

Workaround

Fully exit the app (including tray), then delete the corrupt state and let it regenerate:

Remove-Item "$env:USERPROFILE\.codex\.sandbox\deny_read_acl_state.json" -Force
Remove-Item "$env:USERPROFILE\.codex\.sandbox\setup_error.json" -Force
# only if it is also NUL-filled:
Remove-Item "$env:USERPROFILE\.codex\config.toml" -Force

Both files regenerate correctly on next launch (deny_read_acl_state.json{"principals": {}}), setup completes, and the log shows setup binary completed / read ACL run completed / errors=[]. No reinstall required.

To detect the condition:

$p = "$env:USERPROFILE\.codex\.sandbox\deny_read_acl_state.json"
$b = [System.IO.File]::ReadAllBytes($p)
"NUL bytes: $(($b | Where-Object { $_ -eq 0 }).Count) / $($b.Length)"

Suggested fix

  1. Treat an unparseable deny_read_acl_state.json as empty state rather than a fatal error — log a warning, back the file up, and regenerate the default. Nothing in it is unrecoverable; it rebuilds from {"principals": {}}.
  2. Apply the same tolerance to other CODEX_HOME state files corrupted by the same mechanism (config.toml was hit in the same event).
  3. Write these files atomically (write to a temp file, FlushFileBuffers, then rename) so an unclean shutdown leaves either the old or the new content, never a NUL-filled file.
  4. Surface the underlying parse error in the setup UI. The current screen implies a declined UAC prompt, which sends users toward UAC settings, BIOS virtualization, and reinstalls — none of which can fix a corrupt state file.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingsandboxIssues related to permissions or sandboxingwindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions