{"record":{"id":"72d68067526e478f","repo":"Hmbown/CodeWhale","slug":"ds4-probe-error-config-error-to-string","errorCode":null,"errorMessage":"ds4_probe_error(config, &error.to_string())","messagePattern":"ds4_probe_error\\(config, &error\\.to_string\\(\\)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/doctor.rs","lineNumber":579,"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":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/doctor.rs#L561-L597","documentation":"The doctor's DS4 probe calls `GET /v1/models` on a local DS4 endpoint with a 15-second timeout (tokio::time::timeout around client.list_models()). If the inner request itself errors, the error is formatted via ds4_probe_error(config, ...) and bailed. It means the doctor could not complete the model-listing request against the DS4 server.","triggerScenarios":"probe_ds4_models awaits client.list_models() and receives Ok(Err(error)) — connection refused (server not running), TLS failure, 401/403 from the endpoint, or any reqwest-level error wrapped by the 15s timeout future.","commonSituations":"DS4 server not started or listening on a different port than configured; the endpoint URL in config points at the wrong host; the server requires an API key that is missing or wrong; firewall blocking localhost/port.","solutions":["Read the inner error text rendered by ds4_probe_error — connection refused vs. auth vs. TLS tells you which fix applies.","Confirm the DS4 server is running and reachable: `curl <endpoint>/v1/models`.","Fix the DS4 endpoint URL/API key in the Codewhale config to match the running server.","If auth fails, supply the correct credentials DS4 expects before re-running the doctor."],"exampleFix":"// before: probe fails with ds4_probe_error(...) — connection refused on port 8080\n// after: start DS4 on the configured port or correct the endpoint\nds4 serve --port 8080 &\n# ensure config endpoint = http://127.0.0.1:8080/v1","handlingStrategy":"try-catch","validationCode":"// Probe the endpoint before running the doctor\nlet resp = reqwest::get(format!(\"{endpoint}/v1/models\")).await;\nif let Err(e) = resp {\n    eprintln!(\"DS4 endpoint unreachable: {e}\"); // connection refused / auth / TLS detail\n}","typeGuard":null,"tryCatchPattern":"match probe_result {\n    Err(e) if e.is_connect() => eprintln!(\"start the DS4 server first\"),\n    Err(e) if e.status() == Some(401) => eprintln!(\"check DS4 API key\"),\n    Err(e) => eprintln!(\"DS4 probe failed: {e}\"),\n    Ok(_) => {},\n}","preventionTips":["Confirm the DS4 server is running and its port matches the configured endpoint.","Curl `<endpoint>/v1/models` after any DS4 config change before running the doctor.","Keep DS4 API keys in sync with the Codewhale config."],"tags":["http","diagnostics","doctor","ds4"],"backgroundTag":"api-request-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}