Summary
When openclaw.json contains an unrecognized key (e.g., skills.nano-banana-pro), config validation fails with INVALID_CONFIG. The error handler in src/config/io.ts:802 catches this and returns an empty object {}, silently discarding the entire configuration.
This means every setting falls back to its default value — including security-critical controls.
Impact
A single typo or unrecognized key anywhere in the config causes all of the following to silently revert to defaults:
tools.sessions.visibility → defaults to "tree" (may be more or less restrictive than intended)
channels.telegram.groups → group routing config lost
groupPolicy → reverts to default
- Tool restrictions, model routing, session settings — all gone
- Any security controls configured by the user are silently dropped
The gateway continues running with no visible error to the user (only a log line). The CLI shows a warning but the gateway daemon swallows it.
Root Cause
// src/config/io.ts:801-803
if (error?.code === "INVALID_CONFIG") {
return {}; // ← entire config discarded
}
Validation is all-or-nothing: one invalid key → entire config rejected → empty fallback.
Reproduction
- Add any unrecognized key to
openclaw.json (e.g., "skills": { "my-skill": { "env": { "KEY": "value" } } })
- Restart gateway
- Observe:
tools.sessions.visibility (or any other setting) reverts to default
- Gateway logs show
Invalid config but continues running with empty config
Discovered Via
Setting tools.sessions.visibility: "all" had no effect because an unrelated skills.nano-banana-pro key (documented in a skill's own SKILL.md as valid!) caused the entire config to be discarded. Took significant debugging to trace.
Proposed Fix Options
- Fail hard — refuse to start with invalid config. Safest. Forces user to fix before running. May be too disruptive for some users.
- Partial validation (strip and continue) — remove only unrecognized keys, keep everything else valid. This is what "best-effort" should mean. Zod's
.passthrough() or .strip() could help here.
- Hybrid — strip unknown keys with a loud warning, but fail hard if a known key has an invalid value (type mismatch, constraint violation). This distinguishes "extra stuff I don't understand" from "broken stuff I do understand."
Option 3 seems like the right balance: forward-compatible (new skill keys don't break old versions) while still catching real config errors.
Additional Context
- The skill SKILL.md for
nano-banana-pro explicitly documents skills."nano-banana-pro".env.GEMINI_API_KEY as a valid config path, but the OpenClaw config schema doesn't support arbitrary skill keys. This mismatch makes it easy for users (or agents) to create invalid configs by following skill documentation.
- Consider: should
skills.* be a passthrough/record type to support per-skill config without schema changes?
Summary
When
openclaw.jsoncontains an unrecognized key (e.g.,skills.nano-banana-pro), config validation fails withINVALID_CONFIG. The error handler insrc/config/io.ts:802catches this and returns an empty object{}, silently discarding the entire configuration.This means every setting falls back to its default value — including security-critical controls.
Impact
A single typo or unrecognized key anywhere in the config causes all of the following to silently revert to defaults:
tools.sessions.visibility→ defaults to"tree"(may be more or less restrictive than intended)channels.telegram.groups→ group routing config lostgroupPolicy→ reverts to defaultThe gateway continues running with no visible error to the user (only a log line). The CLI shows a warning but the gateway daemon swallows it.
Root Cause
Validation is all-or-nothing: one invalid key → entire config rejected → empty fallback.
Reproduction
openclaw.json(e.g.,"skills": { "my-skill": { "env": { "KEY": "value" } } })tools.sessions.visibility(or any other setting) reverts to defaultInvalid configbut continues running with empty configDiscovered Via
Setting
tools.sessions.visibility: "all"had no effect because an unrelatedskills.nano-banana-prokey (documented in a skill's own SKILL.md as valid!) caused the entire config to be discarded. Took significant debugging to trace.Proposed Fix Options
.passthrough()or.strip()could help here.Option 3 seems like the right balance: forward-compatible (new skill keys don't break old versions) while still catching real config errors.
Additional Context
nano-banana-proexplicitly documentsskills."nano-banana-pro".env.GEMINI_API_KEYas a valid config path, but the OpenClaw config schema doesn't support arbitrary skill keys. This mismatch makes it easy for users (or agents) to create invalid configs by following skill documentation.skills.*be a passthrough/record type to support per-skill config without schema changes?