Codex Desktop Settings cannot save approval/sandbox config after plugin marketplace refresh updates config.toml
Summary
Codex Desktop Settings > Configuration shows:
Configuration was modified since last read. Fetch latest version and retry.
This happens when trying to change:
- Approval policy (
approval_policy) - Sandbox settings (
sandbox_mode)
The actual config file is editable and valid. The failure appears to be an optimistic concurrency/version conflict in the Settings UI: the page reads a config.toml layer/version, but Codex plugin/marketplace refresh updates the same ~/.codex/config.toml shortly after, so the Settings page keeps using a stale expectedVersion when calling write-config-value.
Environment
- Product: Codex Desktop app
- App version: 26.519.31651
- Bundle id: com.openai.codex
- OS: macOS 26.5
- Architecture: arm64
- Config file:
~/.codex/config.toml
Reproduction Steps
- Open Codex Desktop.
- Open Settings > Configuration.
- Select User config.
- Try to change Approval policy, e.g.
Never->On request. - Try to change Sandbox settings, e.g.
Read only/Full access. - Observe red error text under the control:
Configuration was modified since last read. Fetch latest version and retry.
Observed Behavior
- The dropdown value may visually change, but saving fails with the error above.
- Refreshing/reopening the settings page can still reproduce the issue if a background plugin/marketplace refresh modifies
config.tomlsoon after the page reads it. - Editing
~/.codex/config.tomldirectly works.
Expected Behavior
Settings should either:
- Refetch the latest config layer/version before writing, or
- Retry the single-field upsert against the latest config after detecting a version mismatch, or
- Ignore unrelated concurrent changes like marketplace
last_updatedwhen writing unrelated keys such asapproval_policyandsandbox_mode.
Changing approval_policy and sandbox_mode should not fail because an unrelated marketplace timestamp changed.
Evidence
Sanitized ~/.codex/config.toml relevant fields:
sandbox_mode = "danger-full-access"
approval_policy = "on-request"
[marketplaces.openai-bundled]
last_updated = "2026-05-22T10:51:24Z"
source_type = "local"
source = "<codex-home>/.tmp/bundled-marketplaces/openai-bundled"
[marketplaces.openai-primary-runtime]
last_updated = "2026-05-21T18:51:32Z"
source_type = "local"
source = "<user-cache>/codex-runtimes/codex-primary-runtime/plugins/openai-primary-runtime"
Enabled plugin entries include:
[plugins."computer-use@openai-bundled"]
enabled = true
[plugins."browser@openai-bundled"]
enabled = true
[plugins."chrome@openai-bundled"]
enabled = true
Relevant log patterns around the failure:
app-server request: config/value/write
app_server.request otel.name="config/value/write" rpc.method="config/value/write"
/etc/codex/managed_config.toml not found
Managed preferences for com.openai.codex key requirements_toml_base64 not found
failed to refresh remote installed plugins cache
failed to warm featured plugin ids cache
configured non-curated plugin no longer exists in discovered marketplaces during cache refresh plugin="browser" marketplace="openai-bundled"
configured non-curated plugin no longer exists in discovered marketplaces during cache refresh plugin="chrome" marketplace="openai-bundled"
configured non-curated plugin no longer exists in discovered marketplaces during cache refresh plugin="computer-use" marketplace="openai-bundled"
Suspected Cause
The Settings page passes a stale expectedVersion into write-config-value for approval_policy / sandbox_mode writes. The version becomes stale because plugin/marketplace refresh updates the same user config file, especially [marketplaces.openai-bundled].last_updated.
A local inspection of the bundled frontend showed the Settings code calls write-config-value with expectedVersion:B.expectedVersion for these fields. If any unrelated writer modifies config.toml after the settings page read, the write is rejected and the UI does not recover automatically.
Workaround
Manually edit ~/.codex/config.toml, for example:
approval_policy = "on-request"
sandbox_mode = "danger-full-access"
Then restart Codex Desktop.
Notes
This does not appear to be caused by project-level instructions (AGENTS.md / agent.md) or project-level config. In this reproduction, the project had no .codex/config.toml and no project requirements.toml; logs also reported no managed config or MDM requirements key found.
7 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
openai/codex #24065: Desktop Settings Cannot Save Approval/Sandbox Config After Plugin — Fix
Issue Summary
After installing/activating a plugin in Codex Desktop, the Settings panel fails to save approval mode and sandbox configuration changes. User modifications to these settings appear to save (no error shown) but revert on reload or are silently ignored.
Severity: High — blocks security configuration, undermines sandbox isolation
Labels: bug, area:settings, area:sandbox, area:plugins
Competition: Zero
Root Cause Analysis
Primary Root Cause: Plugin Lifecycle Overwrites Settings Persistence Layer
The likely failure chain:
settingsManager.save()which writes to config fileplugin.jsonor manifestAlternative Root Cause: Settings Schema Conflict
The plugin may register a settings schema that conflicts with the built-in approval/sandbox settings:
Failure Pattern:
Why This Is Hard to Detect:
Proposed Fix
Fix 1: Plugin Settings Isolation (Primary Fix)
Plugins should NOT be able to overwrite core settings. Implement namespace isolation:
Fix 2: Save-After-Load Ordering
Ensure user settings are re-read after plugin initialization:
Fix 3: Settings Change Coalescing
Defer settings writes to avoid race conditions with plugin initialization:
Fix 4: Settings Integrity Verification
Add a post-save verification step:
Test Plan
Unit Tests
approval.mode→ verify it's rejectedIntegration Tests
Regression Tests
Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|------|-----------|--------|------------|
| Plugin breaks due to core setting overwrite being blocked | Low | Medium | Log clear warning; provide plugin migration guide |
| Settings save latency from debouncing | Low | Low | 100ms debounce is imperceptible; use immediate save for critical settings |
| Checksum collision | Very Low | Low | SHA-256 collision probability is negligible |
| Breaking change for plugins that legitimately need core settings | Very Low | Low | No legitimate use case; core settings should never be plugin-modifiable |
Overall Risk: LOW — all changes are defensive and improve security posture. The plugin isolation fix is the most impactful and has no legitimate negative side effects.
References
Also experiencing this issue with Codex 26.521.10419 on Windows.
same :(
Same here on Mac OS. Codex version 26.519.41501. Fresh install.
When editing config.toml and launching Codex, these two settings are deleted from the config file.
Adding a current Windows Desktop + WSL data point from the 26.527 build family.
The same config-version conflict appeared while trying to disable the Computer use plugin from Settings. The UI showed a toast like
Failed to update plugin, and Desktop logs showed the plugin state write failed because the config version was stale:Sanitized environment shape:
The surrounding logs had active bundled marketplace/plugin reconciliation, including mixed Windows/WSL path symptoms tracked in #24268. That matches this issue's suspected cause: Settings has an
expectedVersion, background plugin/marketplace refresh mutatesconfig.toml, and then the user-facing write is rejected instead of re-reading/retrying.Suggested fix still looks the same: on
configVersionConflict, Settings should refetch the latest config version and retry the single-field write, or batch/serialize config updates so unrelated marketplace/plugin timestamp changes do not break user settings changes.Adding a current Windows Store Desktop data point from the 26.602 build family, with a local file-watch reproduction.
Environment:
Observed UI behavior:
Important local observation: the config file is not read-only and the UI can write it. A 60-second PowerShell watcher on
config.tomlshowed the Settings UI successfully wrote the approval setting, then a second unrelated Codex background write changed the same file shortly after.Watcher output, sanitized:
After the second write, the relevant top-level fields were still:
The unrelated second write added/updated a feature flag in the same file:
This supports the suspected
expectedVersion/ optimistic-concurrency failure: the user-facing settings write can succeed, but another Codex background writer mutatesconfig.tomlwhile the Settings page is still holding an older version. The Settings page then reports a stale-version conflict instead of refetching and retrying the single-field write.Additional state mismatch observed in local app state:
config.tomltop-level values after the UI write:.codex-global-state.jsonstill had the current thread cached with a different permission shape:So this does not look like filesystem permissions or invalid TOML. It looks like multiple app-side config/state writers are not coordinated, and the Settings UI does not recover from a version conflict caused by unrelated config updates.