{"record":{"id":"eb680f83952fd2f5","repo":"Hmbown/CodeWhale","slug":"ds4-v1-models-at-did-not-list-configured-alias","errorCode":null,"errorMessage":"DS4 /v1/models at {} did not list configured alias '{configured_alias}' (advertised: {})","messagePattern":"DS4 /v1/models at (.+?) did not list configured alias '(.+?)' \\(advertised: (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/doctor.rs","lineNumber":423,"sourceCode":"        client.list_models(),\n    )\n    .await\n    {\n        Ok(Ok(models)) => models,\n        Ok(Err(error)) => anyhow::bail!(ds4_probe_error(config, &error.to_string())),\n        Err(_) => anyhow::bail!(\"DS4 /v1/models timed out after 15 seconds at {}\", endpoint),\n    };\n    if !models\n        .iter()\n        .any(|available| available.id == configured_alias)\n    {\n        let advertised = models\n            .iter()\n            .take(8)\n            .map(|available| available.id.as_str())\n            .collect::<Vec<_>>()\n            .join(\", \");\n        anyhow::bail!(\n            \"DS4 /v1/models at {} did not list configured alias '{configured_alias}' (advertised: {})\",\n            endpoint,\n            if advertised.is_empty() {\n                \"none\"\n            } else {\n                advertised.as_str()\n            }\n        );\n    }\n    Ok(())\n}\n\nfn ds4_probe_error(config: &crate::config::Config, error: &str) -> String {\n    let endpoint = crate::client::redact_url_for_display(&config.deepseek_base_url());\n    let status = error\n        .split_whitespace()\n        .collect::<Vec<_>>()\n        .windows(2)","sourceCodeStart":405,"sourceCodeEnd":441,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/doctor.rs#L405-L441","documentation":"The DS4 probe listed models successfully, but no advertised id equals `configured_alias` (the model set on the DeepSeek client). The message includes up to 8 advertised ids, or 'none' for an empty catalog, so the alias/server mismatch is visible immediately (doctor.rs:423).","triggerScenarios":"Config sets an alias like `deepseek-chat` while ds4-server advertises different ids; the server's model catalog changed after config was written; alias casing differs from the advertised id; server returns an empty model list.","commonSituations":"ds4-server upgrade renames models; config copied from another environment; typo in the model setting.","solutions":["Set the configured DeepSeek model alias to one of the advertised ids shown in the message","Or reconfigure/restart ds4-server so it advertises the configured alias","Re-run the doctor to confirm the alias now resolves"],"exampleFix":"# before (config)\nmodel = \"deepseek-chat\"\n# after (pick an id the message says is advertised)\nmodel = \"ds4-chat-v2\"","handlingStrategy":"validation","validationCode":"let models = client.list_models().await?;\nlet alias = client.model().to_string();\nanyhow::ensure!(\n    models.iter().any(|m| m.id == alias),\n    \"alias {alias} is not advertised; pick one of: {}\",\n    models.iter().map(|m| m.id.as_str()).collect::<Vec<_>>().join(\", \")\n);","typeGuard":"fn alias_advertised(models: &[DeepSeekModel], alias: &str) -> bool {\n    models.iter().any(|m| m.id == alias)\n}","tryCatchPattern":null,"preventionTips":["Validate the model alias against /v1/models at config load","Re-run the doctor after changing the server's model catalog","Treat the advertised list as the source of truth, not documentation"],"tags":["config","model-registry","deepseek","doctor"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}