Hmbown/CodeWhale · error
Cannot export default_model into a non-table provider slot
Error message
Cannot export default_model into a non-table provider slot
What it means
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.
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
Example fix
# before default_model = "deepseek-reasoner" [providers] deepseek_cn = "oops" # after default_model = "deepseek-reasoner" [providers.deepseek_cn] model = "deepseek-reasoner"
Defensive patterns
Strategy: validation
Validate before calling
if let Some(toml::Value::String(m)) = doc.get("default_model") {
if doc.get("providers").and_then(|p| p.get("deepseek_cn")).map_or(true, |v| v.is_table()) {
// safe to export
}
} Try / catch
if let Err(e) = scrub_root_model_aliases_for_export(&mut doc) {
if e.to_string().contains("default_model") { eprintln!("normalize providers.deepseek_cn table first"); }
return Err(e);
} Prevention
- Keep default_model as a plain string
- Ensure providers.deepseek_cn is a table whenever default_model is set
- Run schema validation before export
When it happens
Trigger: 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.
Common situations: Legacy or hand-edited configs with default_model set and a malformed providers table; partial migrations that left a scalar under providers.deepseek.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Cannot export a root model alias into a non-table provider…
- active profile is missing or malformed
- Cannot export a non-string default_model without losing its…
- config entry must be a string
- config export requires --portable; plain export is not…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/c4dda613739c7146.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/route_preferences.rs:242
);
document.remove(root_key);
}
}
match document.get("default_model").and_then(toml::Value::as_str) {
Some(value) => {
let value = value.trim().to_string();
// A root alias the DeepSeek route still consumes lands in this
// same slot on import; the live choice wins over the dead alias.
let root_covers_slot = active_slot == deepseek_slot
&& ["model", "default_text_model"]
.iter()
.any(|key| document.get(*key).and_then(toml::Value::as_str).is_some());
let folded = !value.is_empty()
&& !root_covers_slot
&& document_slot_value(document, &deepseek_slot).is_none();
if folded {
ensure!(
insert_document_slot_value(document, &deepseek_slot, &value),
"Cannot export default_model into a non-table provider slot"
);
}
document.remove("default_model");
}
None => {
ensure!(
!document.contains_key("default_model"),
"Cannot export a non-string default_model without losing its value"
);
}
}
Ok(())
}
fn project_root_key<'a>(path: &Path, key: &'a str) -> Option<&'a str> {
(codewhale_config::config_path_is_workspace_scoped(path)View on GitHub (pinned to 73e0f67d83)