{"record":{"id":"db12e3d98582b868","repo":"Hmbown/CodeWhale","slug":"ds4-v1-models-returned-http-status-at","errorCode":null,"errorMessage":"DS4 /v1/models returned HTTP {status} at {}","messagePattern":"DS4 /v1/models returned HTTP (.+?) at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/doctor.rs","lineNumber":410,"sourceCode":"}\n\n/// Probe DS4 through its cheap `/v1/models` contract instead of waking the\n/// model for a completion. The selected model must be advertised.\npub(crate) async fn probe_ds4_models(config: &crate::config::Config) -> anyhow::Result<()> {\n    use crate::client::DeepSeekClient;\n    use crate::core::model_client::ModelClient;\n\n    let endpoint = crate::client::redact_url_for_display(&config.deepseek_base_url());\n    let client = DeepSeekClient::new(config)?;\n    let configured_alias = client.model().to_string();\n    let models = match tokio::time::timeout(\n        std::time::Duration::from_secs(15),\n        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 {","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/doctor.rs#L392-L428","documentation":"Emitted by the TUI doctor's DS4 probe (crates/tui/src/doctor.rs). The probe builds a DeepSeekClient from config and calls `list_models()` under a 15-second timeout; transport errors go to `ds4_probe_error`, which scans the error text for an `HTTP <3-digit>` token (doctor.rs:436-458). When one is found, the doctor reports that `/v1/models` answered with that non-success status at the redacted configured base URL.","triggerScenarios":"ds4-server is reachable but returns 401/403 because the configured DeepSeek API key is wrong or missing, 404 because `deepseek_base_url` points at the wrong port or path, or 5xx while the server is failing or starting up.","commonSituations":"Rotated API key still in config; base URL pointing at an auth-gating proxy; a ds4-server version that gates `/v1/models`; server crashing mid-request.","solutions":["Reproduce manually: `curl -i <deepseek_base_url>/models` with the configured key and read the raw status","Fix the API key/credentials used by DeepSeekClient (config or env) for 401/403","Correct `deepseek_base_url` (host, port, path) for 404","Inspect ds4-server logs and restart it for 5xx responses"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let resp = reqwest::Client::new()\n    .get(format!(\"{}/models\", config.deepseek_base_url()))\n    .bearer_auth(config.deepseek_api_key())\n    .send()\n    .await?;\nif !resp.status().is_success() {\n    anyhow::bail!(\"ds4-server unhealthy: HTTP {}\", resp.status());\n}\n// safe to run the doctor probe now","typeGuard":null,"tryCatchPattern":"match probe_ds4(config).await {\n    Ok(()) => {}\n    Err(err) if err.to_string().starts_with(\"DS4 /v1/models returned HTTP\") => {\n        eprintln!(\"doctor: fix ds4-server auth or base URL: {err}\");\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Health-check ds4-server before running the doctor","Manage the DeepSeek API key via a secret source so rotation does not strand stale values","Pin deepseek_base_url to the exact server root; avoid ad-hoc port edits"],"tags":["network","http","diagnostics","deepseek","doctor"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}