Hmbown/CodeWhale · error

Not a model preference key

Error message

Not a model preference key: {key}

What it means

model_slot_for_document resolves which TOML slot (e.g. providers.<id>.model or default_text_model) a saved model preference lives in, for export. It rejects any key that is not a recognized route/model preference key (per is_route_key) or the 'provider' key, because 'provider' does not name a model slot. This is input validation to prevent writing/reading model data under an unknown config path.

Solutions

  1. Pass only keys accepted by is_route_key and not equal to "provider"
  2. Filter the key list through the same is_route_key predicate before calling
  3. Check the key spelling against the documented route keys (model, default_model, default_text_model, providers.<id>.model)

Example fix

// before
let slot = model_slot_for_document(&body, "provider")?;
// after
if is_route_key(key) && key != "provider" {
    let slot = model_slot_for_document(&body, key)?;
}
Defensive patterns

Strategy: validation

Validate before calling

if !is_route_key(key) || key == "provider" { return Err(anyhow!("skip: {key} is not a model preference key")); }

Type guard

fn is_model_pref_key(key: &str) -> bool { is_route_key(key) && key != "provider" }

Prevention

When it happens

Trigger: Calling model_slot_for_document(body, key) with key outside {model, default_model, default_text_model, providers.<id>.model} or with key == "provider"; e.g. passing "provider", a typo like "defaultmodel", or a device-preference key.

Common situations: Export/migration tooling iterating saved Settings keys; key spelling drift after renames; scripts forwarding arbitrary config keys without filtering to model keys.

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


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/44a16b690a9f6cea. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/route_preferences.rs:88

        return Ok(vec!["default_text_model"]);
    }
    let key = match identity.provider {
        ApiProvider::Custom => identity.key.as_str(),
        ApiProvider::DeepseekCN => "deepseek_cn",
        ApiProvider::OllamaCloud if identity.migrated_legacy_ollama_cloud_route => "ollama",
        provider => provider
            .metadata()
            .context("provider model table")?
            .provider_config_key(),
    };
    Ok(vec!["providers", key, "model"])
}

/// Locate the canonical model leaf in a saved document without applying
/// device preferences or launch overrides. Export uses this same identity
/// resolution to omit only root aliases shadowed by that leaf.
pub fn model_slot_for_document(body: &str, key: &str) -> Result<Vec<String>> {
    ensure!(
        is_route_key(key) && key != "provider",
        "Not a model preference key: {key}"
    );
    let config = parse_config(body)?;
    let identity = model_identity(&config, key)?;
    Ok(model_slot(&identity)?
        .into_iter()
        .map(str::to_string)
        .collect())
}

fn document_slot_value(document: &toml::value::Table, slot: &[String]) -> Option<String> {
    let [root, provider, field] = slot else {
        return None;
    };
    document
        .get(root)?
        .as_table()?

View on GitHub (pinned to 73e0f67d83)