{"record":{"id":"ae096bed3013f529","repo":"Hmbown/CodeWhale","slug":"auto-has-no-concrete-route-yet-send-a-turn-before","errorCode":null,"errorMessage":"Auto has no concrete route yet; send a turn before warming its cache","messagePattern":"Auto has no concrete route yet; send a turn before warming its cache","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/tui/ui/provider_routes.rs","lineNumber":401,"sourceCode":"}\n\npub(crate) async fn fetch_available_models(config: &Config) -> Result<Vec<String>> {\n    use crate::client::CodewhaleClient;\n\n    let client = CodewhaleClient::new(config)?;\n    let models = tokio::time::timeout(Duration::from_secs(20), client.list_models()).await??;\n    let mut ids = models.into_iter().map(|model| model.id).collect::<Vec<_>>();\n    ids.sort();\n    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))","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/ui/provider_routes.rs#L383-L419","documentation":"Thrown by resolve_cache_replay_route when cache warmup is requested for the Auto routing mode before Auto has resolved to any concrete provider route. Auto picks a route only after a real turn has been sent; with no turn history there is no concrete provider/endpoint to replay against, so warmup cannot proceed.","triggerScenarios":"Calling run_cache_warmup -> resolve_cache_replay_route while app.cache_replay_target() returns None — i.e. triggering prompt-cache warmup with route set to Auto in a fresh session with zero completed turns, or after state that cleared the last resolved route.","commonSituations":"Warming the cache immediately after launching a new session pinned to Auto; running warmup after clearing conversation history; scripts that invoke warmup before the first user turn completes.","solutions":["Send at least one turn normally first; Auto then records a concrete route and warmup succeeds.","Pin the route to a specific provider/model instead of Auto if you need warmup before any turn.","Skip warmup when app.cache_replay_target() is None rather than calling resolve_cache_replay_route.","If a turn was already sent but the target is still None, check that route resolution persisted the last concrete route."],"exampleFix":"// before\nlet route = resolve_cache_replay_route(app, config)?;\nwarm_cache(route).await?;\n// after\nif let Ok(route) = resolve_cache_replay_route(app, config) {\n    warm_cache(route).await?;\n} // else: Auto not yet resolved; skip warmup until first turn completes","handlingStrategy":"fallback","validationCode":"// skip warmup when Auto has not resolved a concrete route\nfn warmup_ready(app: &App) -> bool {\n    app.cache_replay_target().is_some()\n}","typeGuard":null,"tryCatchPattern":"match resolve_cache_replay_route(app, config) {\n    Ok(route) => warm_cache(route).await?,\n    Err(e) if e.to_string().contains(\"no concrete route\") => {\n        tracing::debug!(\"skipping warmup: Auto not yet resolved\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Only trigger cache warmup after at least one completed turn in Auto mode.","Pin an explicit provider/model route when warmup must run before any turn.","Gate warmup calls on cache_replay_target().is_some().","Re-check the resolved route after clearing conversation history."],"tags":["routing","cache","warmup","auto-route"],"backgroundTag":"invalid-state-transition","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"}