{"record":{"id":"b967a6f2ee766922","repo":"Hmbown/CodeWhale","slug":"segment-in-config-toml-must-be-a-table","errorCode":null,"errorMessage":"`{segment}` in config.toml must be a table","messagePattern":"`(.+?)` in config\\.toml must be a table","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/config/src/config_document.rs","lineNumber":437,"sourceCode":"    let mut current: &mut dyn toml_edit::TableLike = root;\n    for segment in segments {\n        if current.get(segment).is_none() {\n            match lookup {\n                PathLookup::Create => {\n                    let mut table = toml_edit::Table::new();\n                    table.set_implicit(true);\n                    current.insert(segment, toml_edit::Item::Table(table));\n                }\n                PathLookup::Existing => return Ok(None),\n            }\n        }\n        let item = current\n            .get_mut(segment)\n            .expect(\"segment exists or was inserted above\");\n        match item.as_table_like_mut() {\n            Some(table) => current = table,\n            None => match lookup {\n                PathLookup::Create => bail!(\"`{segment}` in config.toml must be a table\"),\n                PathLookup::Existing => return Ok(None),\n            },\n        }\n    }\n    Ok(Some(current))\n}\n\n#[cfg(test)]\nmod tests {\n    #[test]\n    fn healing_lifts_nested_extras_towers_to_the_top_level() {\n        let tmp = tempfile::tempdir().expect(\"tempdir\");\n        let path = tmp.path().join(\"config.toml\");\n        std::fs::write(\n            &path,\n            concat!(\n                \"reasoning_effort = \\\"high\\\"\\n\\n\",\n                \"[projects.\\\"/live\\\"]\\n\",","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/config/src/config_document.rs#L419-L455","documentation":"While walking/creating a dotted config path (set_config_document_value with PathLookup::Create), an existing intermediate segment in config.toml is not a table-like item (it is a scalar, array, or array-of-tables), so it cannot be descended into. The message names the offending top-level segment.","triggerScenarios":"Code sets a nested value like `model.provider = \"acme\"` while config.toml already contains a scalar at the same key, e.g. `model = \"gpt-4o\"` at top level; the descent hits a non-table item and bails instead of overwriting user data.","commonSituations":"Config schema drift after upgrading Codewhale (a key that used to be a string is now a table); hand-written minimal configs that set `model = \"...\"`; leftover keys from an older config format colliding with new nested settings.","solutions":["Edit config.toml and convert the named scalar into a table, moving the old value under an appropriate key inside it","Remove the stale key entirely and let Codewhale write the nested structure fresh","After upgrading Codewhale, run any provided config migration/doctor command before setting nested options"],"exampleFix":"# before (config.toml)\nmodel = \"gpt-4o\"\n\n# after (config.toml)\n[model]\nname = \"gpt-4o\"\n# or simply remove the line and re-apply settings","handlingStrategy":"type-guard","validationCode":"// Before setting a nested value, ensure every prefix segment is table-like:\nfn path_segments_are_tables(doc: &toml_edit::DocumentMut, segments: &[&str]) -> bool {\n    let mut cur = doc.as_table();\n    for seg in segments {\n        match cur.get(*seg) {\n            None | Some(toml_edit::Item::Table(_)) => return true, // creatable\n            Some(item) if item.is_table_like() => { /* descend */ }\n            _ => return false, // scalar/array blocks Create\n        }\n    }\n    true\n}","typeGuard":"fn is_table_like(item: &toml_edit::Item) -> bool {\n    item.as_table_like().is_some()\n}","tryCatchPattern":"match set_config_document_value(&mut doc, segments, value) {\n    Ok(Some(_)) => { /* applied */ }\n    Ok(None) | Err(_) if seg_conflicts(config_text, segments) => {\n        // show the offending scalar and offer migration to [table] form\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["After upgrades, lint config.toml for scalar keys that the new schema expects as tables","Prefer fully-qualified nested keys when writing config programmatically","Back up config.toml before schema-migrating versions"],"tags":["config","toml","schema","type-mismatch"],"backgroundTag":"config-type-mismatch","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}