{"record":{"id":"6393016466d1cae9","repo":"Hmbown/CodeWhale","slug":"saved-cache-route-identity-now-resolves-as","errorCode":null,"errorMessage":"saved cache route identity `{}` now resolves as {}/{} instead of {}/{}; send a new turn before warming","messagePattern":"saved cache route identity `(.+?)` now resolves as (.+?)/(.+?) instead of (.+?)/(.+?); send a new turn before warming","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/tui/ui/provider_routes.rs","lineNumber":410,"sourceCode":"    ids.dedup();\n    Ok(ids)\n}\n\npub(crate) fn resolve_cache_replay_route(\n    app: &App,\n    config: &Config,\n) -> Result<crate::route_runtime::ResolvedRuntimeRoute> {\n    let target = app.cache_replay_target().ok_or_else(|| {\n        anyhow::anyhow!(\"Auto has no concrete route yet; send a turn before warming its cache\")\n    })?;\n    let identity = config\n        .resolve_persisted_provider_identity(\n            Some(target.provider.as_str()),\n            target.provider_id.as_deref(),\n        )\n        .map_err(anyhow::Error::msg)?;\n    if identity.provider != target.provider || identity.key != target.provider_identity {\n        anyhow::bail!(\n            \"saved cache route identity `{}` now resolves as {}/{} instead of {}/{}; send a new turn before warming\",\n            target.provider_identity,\n            identity.provider.as_str(),\n            identity.key,\n            target.provider.as_str(),\n            target.provider_identity\n        );\n    }\n    let route = resolve_runtime_route_for_identity(config, &identity, Some(&target.model))\n        .map_err(anyhow::Error::msg)?;\n    if let Some(previous_base_url) = target.base_url.as_deref() {\n        let previous_endpoint = crate::route_receipt::endpoint_identity(previous_base_url);\n        let current_endpoint =\n            crate::route_receipt::endpoint_identity(&route.candidate.endpoint().base_url);\n        if previous_endpoint != current_endpoint {\n            anyhow::bail!(\n                \"the cache route endpoint changed since the last turn; send a new turn before warming\"\n            );","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/ui/provider_routes.rs#L392-L428","documentation":"The cache-warmup path resolves the persisted provider route (`target`) again before warming. If the saved identity now resolves to a different provider or key than recorded, warming would prime the wrong provider's cache, so it bails and tells the user to send a new turn first (which re-captures a correct route).","triggerScenarios":"Calling `resolve_cache_replay_route` (via run_cache_warmup) when `resolve_persisted_provider_identity(target.provider, target.provider_id)` returns an identity whose `provider` or `key` differs from `target.provider`/`target.provider_identity` — e.g. a provider alias, profile, or default model changed since the route was saved.","commonSituations":"Auto model selection now picks a different provider after a config or model-registry update; provider renamed/re-registered; resuming a session saved before a provider change and running cache warmup immediately.","solutions":["Send a new turn first (as the message says) so a fresh, correct route is persisted, then run cache warmup","Update the saved/provider configuration so the identity resolves to the same provider/key as when saved","If the provider was intentionally changed, clear the stale cached route entry instead of replaying it"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let identity = config.resolve_persisted_provider_identity(\n    Some(target.provider.as_str()), target.provider_id.as_deref())?;\nif identity.provider != target.provider || identity.key != target.provider_identity {\n    eprintln!(\"saved cache route is stale; send a new turn before warming\");\n    return;\n}","typeGuard":"fn route_still_resolves(c: &Config, t: &CacheTarget) -> bool {\n    c.resolve_persisted_provider_identity(\n        Some(t.provider.as_str()), t.provider_id.as_deref())\n        .map_or(false, |i| i.provider == t.provider && i.key == t.provider_identity)\n}","tryCatchPattern":"match resolve_cache_replay_route(...).await {\n    Err(e) if e.to_string().contains(\"now resolves as\") => {\n        // skip warmup; the next normal turn re-persists a valid route\n        skip_warmup();\n    }\n    r => r,\n}","preventionTips":["Run cache warmup only right after a successful turn in the same configuration","Clear stale cached routes after changing provider aliases or defaults","Re-send a turn after any provider/model configuration change before warming"],"tags":["rust","provider","cache","routing"],"backgroundTag":"stale-route-identity","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}