Hmbown/CodeWhale · warning
saved cache route identity
Error message
saved cache route identity `{}` now resolves as {}/{} instead of {}/{}; send a new turn before warming What it means
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).
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
Defensive patterns
Strategy: validation
Validate before calling
let identity = config.resolve_persisted_provider_identity(
Some(target.provider.as_str()), target.provider_id.as_deref())?;
if identity.provider != target.provider || identity.key != target.provider_identity {
eprintln!("saved cache route is stale; send a new turn before warming");
return;
} Type guard
fn route_still_resolves(c: &Config, t: &CacheTarget) -> bool {
c.resolve_persisted_provider_identity(
Some(t.provider.as_str()), t.provider_id.as_deref())
.map_or(false, |i| i.provider == t.provider && i.key == t.provider_identity)
} Try / catch
match resolve_cache_replay_route(...).await {
Err(e) if e.to_string().contains("now resolves as") => {
// skip warmup; the next normal turn re-persists a valid route
skip_warmup();
}
r => r,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- translation route changed after turn dispatch; refusing to…
- Auto has no concrete route yet; send a turn before warming…
- bounded fragment module missing required marker
- catalog cache unavailable
- Failed to resolve runtime thread route
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/6393016466d1cae9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/ui/provider_routes.rs:410
ids.dedup();
Ok(ids)
}
pub(crate) fn resolve_cache_replay_route(
app: &App,
config: &Config,
) -> Result<crate::route_runtime::ResolvedRuntimeRoute> {
let target = app.cache_replay_target().ok_or_else(|| {
anyhow::anyhow!("Auto has no concrete route yet; send a turn before warming its cache")
})?;
let identity = config
.resolve_persisted_provider_identity(
Some(target.provider.as_str()),
target.provider_id.as_deref(),
)
.map_err(anyhow::Error::msg)?;
if identity.provider != target.provider || identity.key != target.provider_identity {
anyhow::bail!(
"saved cache route identity `{}` now resolves as {}/{} instead of {}/{}; send a new turn before warming",
target.provider_identity,
identity.provider.as_str(),
identity.key,
target.provider.as_str(),
target.provider_identity
);
}
let route = resolve_runtime_route_for_identity(config, &identity, Some(&target.model))
.map_err(anyhow::Error::msg)?;
if let Some(previous_base_url) = target.base_url.as_deref() {
let previous_endpoint = crate::route_receipt::endpoint_identity(previous_base_url);
let current_endpoint =
crate::route_receipt::endpoint_identity(&route.candidate.endpoint().base_url);
if previous_endpoint != current_endpoint {
anyhow::bail!(
"the cache route endpoint changed since the last turn; send a new turn before warming"
);View on GitHub (pinned to 73e0f67d83)