Hmbown/CodeWhale · error
`config set` does not support nested key
Error message
`config set` does not support nested key `{key}`; edit `{field}` in the [{table}] table of config.toml instead (use a TOML value of the documented type). No value was changed. What it means
`config set` only supports flat, scalar keys. Any dotted key other than the specially-handled mcp.server_definitions is treated as nested TOML and rejected, telling the user which table and field to edit by hand in config.toml. Nothing is written when this fires.
Solutions
- Edit config.toml directly: set `field` inside the `[table]` section with a correctly typed TOML value
- Use the dedicated subcommand for nested features where one exists (e.g. MCP server management)
- For mcp.server_definitions specifically, pass JSON text — it is persisted as a literal string, not TOML nesting
Example fix
// before codewhale config set notifications.slack.webhook_url https://hooks.example/T123 // after # edit config.toml: [notifications.slack] webhook_url = "https://hooks.example/T123"
Defensive patterns
Strategy: validation
Validate before calling
if key.contains('.') && key != "mcp.server_definitions" {
let (table, field) = key.rsplit_once('.').unwrap();
return Err(format!("edit `{field}` in the [{table}] table of config.toml directly"));
} Try / catch
match config.set(key, value) {
Err(e) if e.to_string().contains("does not support nested key") => {
eprintln!("{e}"); // guidance names the exact table/field to edit
}
other => other?,
} Prevention
- Restrict CLI setters to flat keys
- Edit nested settings in config.toml with a correctly typed TOML value
- Special-case mcp.server_definitions as JSON text
- Warn users in tooling before they attempt dotted keys
When it happens
Trigger: `codewhale config set <table>.<field> <value>` for any nested setting except mcp.server_definitions — e.g. `config set notifications.slack.webhook_url https://...` or `config set mcp.foo.bar 1`.
Common situations: Scripting nested configuration; assuming `config set` mirrors every config.toml key; trying to set a table-valued or deeply nested option from the CLI.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- account_agent_model_unconfigured
- active profile is missing or malformed
- bundle at is bytes; the limit is bytes
- bundle at is bytes; the limit is bytes
- Cannot export a non-string default_model without losing its…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/daabe118add8ca78.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/lib.rs:2993
"telemetry" => {
self.telemetry = Some(parse_bool(value)?);
}
// Scheme rules (HTTPS, or loopback HTTP) are enforced where a
// batch would actually be sent, not here: a user must be able to
// stage a value before the machinery that reads it exists.
"telemetry_endpoint" => self.telemetry_endpoint = Some(value.to_string()),
"approval_policy" => self.approval_policy = Some(value.to_string()),
"sandbox_mode" => self.sandbox_mode = Some(value.to_string()),
"hook_sinks.unix_socket_path" => {
self.hook_sinks
.get_or_insert_with(HookSinksToml::default)
.unix_socket_path = Some(PathBuf::from(value));
}
// The MCP stdio dispatcher persists this established literal key
// as JSON text; it is not a nested TOML setting.
_ if key.contains('.') && key != "mcp.server_definitions" => {
let (table, field) = key.rsplit_once('.').expect("dotted key");
bail!(
"`config set` does not support nested key `{key}`; edit `{field}` in the [{table}] table of config.toml instead (use a TOML value of the documented type). No value was changed."
);
}
_ => {
self.extras
.insert(key.to_string(), toml::Value::String(value.to_string()));
}
}
Ok(())
}
pub fn unset_value(&mut self, key: &str) -> Result<()> {
if notifications::in_namespace(key) {
let setting = notifications::NotificationSetting::required(key)?;
return notifications::edit_extras(&mut self.extras, setting, None);
}
if let Some((provider_id, model)) = parse_model_context_window_key(key) {
self.unset_model_context_window(provider_id, model);View on GitHub (pinned to 73e0f67d83)