Hmbown/CodeWhale · error

Not a route preference key

Error message

Not a route preference key: {key}

What it means

get reads the saved route preference for a key without applying launch overrides or credentials. It first validates the key with is_route_key and rejects anything that is not a provider or model selection key. This keeps reads from silently returning data for unknown or device-specific keys.

Solutions

  1. Use a valid route key: provider, model, default_model, default_text_model, or providers.<id>.model
  2. Validate with is_route_key(key) before calling get
  3. Correct the key spelling

Example fix

// before
let v = get(&path, "model_provider")?;
// after
let v = get(&path, "provider")?;
Defensive patterns

Strategy: validation

Validate before calling

if !is_route_key(key) { return Err(anyhow!("{key} is not a route preference key")); }

Type guard

fn is_route_key(key: &str) -> bool {
    matches!(key, "provider"|"model"|"default_model"|"default_text_model")
        || key.strip_prefix("providers.").and_then(|r| r.strip_suffix(".model")).is_some_and(|id| !id.is_empty())
}

Try / catch

match get(&path, key) {
    Ok(v) => v,
    Err(e) if e.to_string().contains("Not a route preference key") => { eprintln!("use provider|model|default_model|default_text_model|providers.<id>.model"); None }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling route_preferences::get(path, key) with key not in {provider, model, default_model, default_text_model, providers.<id>.model}; e.g. typos like "models" or arbitrary config keys.

Common situations: Scripts querying route state with mistyped key names; callers assuming any config key is readable through this API.

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/e0392d95b3089e79. Report an issue: GitHub.

Appendix: source

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

        original
    } else {
        rendered = store.rendered_body()?;
        &rendered
    };
    let mut config = parse_config(body)?;
    if config.route_preferences_version.is_none()
        && crate::config::is_home_config_path(store.path())
    {
        config.apply_saved_selection(
            &crate::settings::Settings::load_legacy_route_preferences_read_only()?,
        );
    }
    Ok(config)
}

/// Read the saved route without applying launch overrides or credentials.
pub fn get(path: &Path, key: &str) -> Result<Option<String>> {
    ensure!(is_route_key(key), "Not a route preference key: {key}");
    let store = codewhale_config::ConfigStore::load(Some(path.to_path_buf()))?;
    if let Some(key) = project_root_key(store.path(), key) {
        return Ok(store.config.get_value(key));
    }
    let mut config = saved_config(&store)?;
    if key == "provider" {
        return Ok(Some(
            config.provider.unwrap_or_else(|| "deepseek".to_string()),
        ));
    }
    let identity = model_identity(&config, key)?;
    config.scope_to_provider_identity(&identity);
    Ok(config
        .provider_config_for(identity.provider)
        .and_then(|entry| entry.model.clone())
        .or_else(|| {
            (provider_model_id(key).is_none()
                && (config.default_text_model.is_some() || config.legacy_model.is_some()))

View on GitHub (pinned to 73e0f67d83)