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

  1. Make providers.<deepseek> a TOML table with a model field before exporting
  2. Manually move the default_model value into providers.<deepseek>.model and remove default_model
  3. 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

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


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)