{"record":{"id":"c4dda613739c7146","repo":"Hmbown/CodeWhale","slug":"cannot-export-default-model-into-a-non-table-provider-slot","errorCode":null,"errorMessage":"Cannot export default_model into a non-table provider slot","messagePattern":"Cannot export default_model into a non-table provider slot","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/route_preferences.rs","lineNumber":242,"sourceCode":"            );\n            document.remove(root_key);\n        }\n    }\n\n    match document.get(\"default_model\").and_then(toml::Value::as_str) {\n        Some(value) => {\n            let value = value.trim().to_string();\n            // A root alias the DeepSeek route still consumes lands in this\n            // same slot on import; the live choice wins over the dead alias.\n            let root_covers_slot = active_slot == deepseek_slot\n                && [\"model\", \"default_text_model\"]\n                    .iter()\n                    .any(|key| document.get(*key).and_then(toml::Value::as_str).is_some());\n            let folded = !value.is_empty()\n                && !root_covers_slot\n                && document_slot_value(document, &deepseek_slot).is_none();\n            if folded {\n                ensure!(\n                    insert_document_slot_value(document, &deepseek_slot, &value),\n                    \"Cannot export default_model into a non-table provider slot\"\n                );\n            }\n            document.remove(\"default_model\");\n        }\n        None => {\n            ensure!(\n                !document.contains_key(\"default_model\"),\n                \"Cannot export a non-string default_model without losing its value\"\n            );\n        }\n    }\n    Ok(())\n}\n\nfn project_root_key<'a>(path: &Path, key: &'a str) -> Option<&'a str> {\n    (codewhale_config::config_path_is_workspace_scoped(path)","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/route_preferences.rs#L224-L260","documentation":"Export scrubs the root default_model key by folding its value into the DeepSeek provider table slot (providers.deepseek_cn.model or equivalent). If that slot cannot receive the value because the provider entry is not a table, the export aborts instead of removing default_model and losing the setting. It is a data-loss guard during config export.","triggerScenarios":"Exporting a document that has a non-empty string default_model, where default_model does not already cover the DeepSeek slot, and providers.<deepseek-slot-id> exists as a non-table value so insert_document_slot_value returns false.","commonSituations":"Legacy or hand-edited configs with default_model set and a malformed providers table; partial migrations that left a scalar under providers.deepseek.","solutions":["Make providers.<deepseek> a TOML table with a model field before exporting","Manually move the default_model value into providers.<deepseek>.model and remove default_model","Normalize the config via the app's normal save path, then retry export"],"exampleFix":"# before\ndefault_model = \"deepseek-reasoner\"\n[providers]\ndeepseek_cn = \"oops\"\n# after\ndefault_model = \"deepseek-reasoner\"\n[providers.deepseek_cn]\nmodel = \"deepseek-reasoner\"","handlingStrategy":"validation","validationCode":"if let Some(toml::Value::String(m)) = doc.get(\"default_model\") {\n    if doc.get(\"providers\").and_then(|p| p.get(\"deepseek_cn\")).map_or(true, |v| v.is_table()) {\n        // safe to export\n    }\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = scrub_root_model_aliases_for_export(&mut doc) {\n    if e.to_string().contains(\"default_model\") { eprintln!(\"normalize providers.deepseek_cn table first\"); }\n    return Err(e);\n}","preventionTips":["Keep default_model as a plain string","Ensure providers.deepseek_cn is a table whenever default_model is set","Run schema validation before export"],"tags":["config","toml","export"],"backgroundTag":"incompatible-source-type","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}