openclaw - 💡(How to fix) Fix Plugin config in openclaw.json is RO inside NemoClaw sandbox — needs writable overlay path or env-var fallback for runtime reconfig [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#72944Fetched 2026-04-28 06:29:48
View on GitHub
Comments
1
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
cross-referenced ×3closed ×1commented ×1

Error Message

→ EACCES (no error explanation surfaces; user thinks they typo'd a path)

Code Example

# edit ~/.openclaw/openclaw.json
# restart gateway
# done

---

# edit /sandbox/.openclaw/openclaw.json
# → EACCES (no error explanation surfaces; user thinks they typo'd a path)

---

$ openshell sandbox exec -n <sandbox> -- vim /sandbox/.openclaw/openclaw.json
# vim opens — file looks editable
# :wq
# E212: Can't open file for writing  (EACCES)

---

// On gateway startup, for each plugin:
const baseConfig = openclawJson.plugins.entries[id].config ?? {};
const overlayPath = path.join(OPENCLAW_DATA, 'plugin-config', `${id}.json`);
const overlayConfig = fs.existsSync(overlayPath) ? JSON.parse(fs.readFileSync(overlayPath)) : {};
const finalConfig = { ...baseConfig, ...overlayConfig };
RAW_BUFFERClick to expand / collapse

In plain English: plugin configuration today lives in openclaw.json:plugins.entries.<id>.config, which is editable on a normal host install but read-only at runtime in NemoClaw / OpenShell sandboxes (the /sandbox/.openclaw/ directory is Landlock-RO). That means every config change requires rebuilding the sandbox image — even for a single endpoint URL flip during debugging. A second writable location for plugin config (overlay file) OR support for environment-variable overrides for common settings would unblock iterative development without sacrificing the security model.

Problem

OpenClaw plugins read their configuration from plugins.entries.<id>.config in openclaw.json. On a normal host install, that file is editable — change config, restart gateway, done. In a NemoClaw / OpenShell sandbox, however, the entire /sandbox/.openclaw/ directory tree is Landlock-read-only at runtime (security hardening — prevents agents from tampering with auth tokens or CORS).

So any plugin that requires per-deployment configuration — OTLP endpoint, service name, API tokens, logging verbosity — must have that config baked at image build time. Every config change is a sandbox image rebuild, which is multi-minute and forces a sandbox recreate.

What a user expects:

# edit ~/.openclaw/openclaw.json
# restart gateway
# done

What actually happens in a sandbox:

# edit /sandbox/.openclaw/openclaw.json
# → EACCES (no error explanation surfaces; user thinks they typo'd a path)

The bifurcation between writable extensions (/sandbox/.openclaw-data/extensions/) and read-only config (/sandbox/.openclaw/openclaw.json) is unmentioned in any docs.

Reproducer

$ openshell sandbox exec -n <sandbox> -- vim /sandbox/.openclaw/openclaw.json
# vim opens — file looks editable
# :wq
# E212: Can't open file for writing  (EACCES)

Tested-against: NemoClaw v0.0.26 sandbox running OpenClaw v2026.4.9.

Proposed fix

Three improvements that compose:

1. Sourceable overlay path for plugin config.

Make plugins.entries.<id>.config resolve from a writable overlay path (e.g., /sandbox/.openclaw-data/plugin-config/<id>.json or a single /sandbox/.openclaw-data/plugin-config.json) so config can change at runtime without a rebuild. The base openclaw.json stays Landlock-RO; per-plugin config overlays from the writable area.

Implementation pattern:

// On gateway startup, for each plugin:
const baseConfig = openclawJson.plugins.entries[id].config ?? {};
const overlayPath = path.join(OPENCLAW_DATA, 'plugin-config', `${id}.json`);
const overlayConfig = fs.existsSync(overlayPath) ? JSON.parse(fs.readFileSync(overlayPath)) : {};
const finalConfig = { ...baseConfig, ...overlayConfig };

Plugin authors don't have to do anything new. Operators get an editable surface.

2. Standard OTel env-var support in deep-observability (and any plugin that exposes OTel-like settings).

OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_SERVICE_NAME etc. are already-standardized OpenTelemetry env vars. Plugins that emit OTel data should honor them as fallback when config doesn't set them. (This is the outshift-open/openclaw-deep-observability sibling issue for the plugin side.) For the OpenClaw core side, providing a documented "plugins should read X env vars" pattern is the equivalent shape.

3. Document the build-time-only constraint loudly in NemoClaw / OpenShell docs.

Until (1) and (2) land, at minimum: a docs page that explains the bifurcation (writable extensions vs RO config) so operators know to bake config at image build time rather than spending an afternoon debugging EACCES.

Alternatives considered

  • Make /sandbox/.openclaw/ partially writable. Defeats the security model; would need a more-targeted overlay anyway.
  • Plugin-specific env vars per plugin (no standard). Works but each plugin has to reinvent the convention. Standard OTel env vars are a free win for OTel-ish plugins.
  • Move all config to env vars and skip JSON entirely. Too prescriptive; JSON config is a reasonable shape for complex structures.

Test plan

  • Cold install: bake a plugin config with default endpoint into image; at runtime, drop an overlay JSON in /sandbox/.openclaw-data/plugin-config/<id>.json, restart gateway, confirm the overlay endpoint is in effect.
  • Env-var fallback (for plugins that add it): set OTEL_EXPORTER_OTLP_ENDPOINT in sandbox env, no overlay file present, no JSON config.endpoint — confirm the env var is honored.
  • Backwards compat: bare openclaw.json config without any overlay continues to work as today.

Risk / blast radius

  • (1) Overlay path is purely additive — no change to existing config-loading behavior unless the overlay file exists. Backwards-compatible.
  • (2) Env-var fallback requires per-plugin support; no change to OpenClaw core unless we standardize a "plugins should read these env vars" interface and document it.
  • (3) Docs is risk-free.

Open questions

  1. Preferred overlay location — single file (/sandbox/.openclaw-data/plugin-config.json with per-plugin keys) or per-plugin files (/sandbox/.openclaw-data/plugin-config/<id>.json)?
  2. Should the overlay merge be deep (recursive merge of nested objects) or shallow (top-level keys only)? Deep merge is more flexible but harder to reason about; shallow is simpler.
  3. Is plugins.entries.<id>.config.fromEnv something the schema would accept — explicit list of which env vars to fall back to per plugin? Lets each plugin declare its env-var contract without OpenClaw core having to know about specific env vars.
  4. Sibling issue at outshift-open/openclaw-deep-observability for the plugin-side env-var support — happy to reference once filed.

Tested-against: OpenClaw v2026.4.9 inside a NemoClaw v0.0.26 sandbox. Sibling findings: #72938 (plugins install path), #72939 (mDNS crash), #72941 (async register truncated), #72942 (gateway stop no-op), forthcoming for double plugin-load timing.

extent analysis

TL;DR

To resolve the issue, introduce a sourceable overlay path for plugin config and support environment-variable overrides for common settings, allowing for runtime configuration changes without requiring a sandbox image rebuild.

Guidance

  • Introduce a writable overlay path (e.g., /sandbox/.openclaw-data/plugin-config/<id>.json) to store plugin configurations, enabling runtime changes without rebuilding the sandbox image.
  • Implement environment-variable overrides for common settings, such as OTEL_EXPORTER_OTLP_ENDPOINT, to provide a fallback when the config doesn't set them.
  • Document the build-time-only constraint and the new overlay path in NemoClaw / OpenShell docs to avoid confusion and facilitate iterative development.
  • Consider implementing a deep merge for overlay configurations to allow for more flexibility, but weigh the trade-offs with simplicity and reasoning complexity.

Example

const overlayPath = path.join(OPENCLAW_DATA, 'plugin-config', `${id}.json`);
const overlayConfig = fs.existsSync(overlayPath) ? JSON.parse(fs.readFileSync(overlayPath)) : {};
const finalConfig = { ...baseConfig, ...overlayConfig };

Notes

The proposed solution involves introducing a new overlay path and supporting environment-variable overrides, which may require additional testing and validation to ensure backwards compatibility and security.

Recommendation

Apply the workaround by introducing a sourceable overlay path for plugin config and supporting environment-variable overrides, as this approach allows for runtime configuration changes without sacrificing the security model and enables iterative development.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Plugin config in openclaw.json is RO inside NemoClaw sandbox — needs writable overlay path or env-var fallback for runtime reconfig [1 comments, 1 participants]