#12012: Gateway/Plugins: skip auto-enable config write in Nix mode
gateway
stale
size: XS
Cluster:
Gateway and macOS Improvements
## Summary
- Skip `writeConfigFile` in the plugin auto-enable code path when `OPENCLAW_NIX_MODE=1` is set
- Log detected auto-enable changes as info without persisting to disk
- Consistent with the existing `isNixMode` guard on legacy config migration
## Problem
When the gateway starts in Nix mode, the config file (`openclaw.json`) is a read-only symlink to the Nix store. The `applyPluginAutoEnable` code path calls `writeConfigFile()` unconditionally, which:
1. Tries an atomic rename (fails — read-only nix store)
2. Falls back to `copyFile()`, replacing the symlink with a regular file
3. Subsequent `home-manager switch` fails with "Existing file would be clobbered"
The legacy migration path already checks `isNixMode` and throws instead of writing, but the plugin auto-enable path was missing this guard.
## Fix
When `isNixMode` is true, skip the `writeConfigFile` call and log the changes as informational only. In Nix mode, plugins should be declared in the Nix config rather than auto-enabled at runtime.
Related: openclaw/nix-openclaw#50, openclaw/nix-openclaw#51
## Test plan
- [ ] Start gateway with `OPENCLAW_NIX_MODE=1` and a config that triggers plugin auto-enable (e.g. telegram channel configured)
- [ ] Verify config symlink is preserved (not replaced with regular file)
- [ ] Verify log shows "skipping plugin auto-enable persistence (Nix mode)" message
- [ ] Verify normal (non-Nix) mode still writes config as before
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This change updates gateway startup so that when `OPENCLAW_NIX_MODE=1` is detected (`isNixMode`), plugin auto-enable changes are **logged but not persisted** to `openclaw.json`. In normal (non-Nix) mode the previous behavior remains: auto-enable updates are written via `writeConfigFile()` and then logged.
This fits alongside the existing Nix-mode behavior earlier in `startGatewayServer()` where legacy config migration is blocked from writing to disk. The net effect is to avoid clobbering a read-only/symlinked config file in Nix-managed setups while keeping auto-enable persistence for standard installs.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk.
- The change is narrowly scoped to a single startup code path and only alters persistence behavior behind an existing `isNixMode` guard. The non-Nix path preserves prior write-and-log semantics, and the Nix path avoids an expected failure mode (attempting to write to an immutable/symlinked config). No other code paths are affected.
- No files require special attention
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#11455: fix(gateway): default gateway.mode to local when unset
by AnonO6 · 2026-02-07
78.4%
#6770: fix(gateway): protect host-local transport fields from config.patch
by ryx2 · 2026-02-02
75.9%
#21931: feat(config): auto-rollback to last known-good backup on invalid co...
by Protocol-zero-0 · 2026-02-20
73.4%
#23780: Gateway: fail closed on insecure state directory permissions
by bmendonca3 · 2026-02-22
73.0%
#23719: Gateway: fail closed startup on insecure state/config permissions
by bmendonca3 · 2026-02-22
73.0%
#11602: fix(config): skip stale legacy config files when openclaw.json exists
by akoscz · 2026-02-08
72.8%
#23779: fix(config): auto-repair invalid config keys from backup on load
by cintia09 · 2026-02-22
72.6%
#5823: fix(config): exit cleanly on invalid config instead of high CPU loop
by gavinbmoore · 2026-02-01
72.5%
#19129: fix(config): block destructive config writes instead of only loggin...
by pierreeurope · 2026-02-17
72.1%
#23364: Gateway: add risk-ack interlock for dangerous Control UI flags
by bmendonca3 · 2026-02-22
72.0%