Hmbown/CodeWhale · error
ds4_probe_error(config, &error.to_string())
Error message
ds4_probe_error(config, &error.to_string())
What it means
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.
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.
Example fix
// before: probe fails with ds4_probe_error(...) — connection refused on port 8080 // after: start DS4 on the configured port or correct the endpoint ds4 serve --port 8080 & # ensure config endpoint = http://127.0.0.1:8080/v1
Defensive patterns
Strategy: try-catch
Validate before calling
// Probe the endpoint before running the doctor
let resp = reqwest::get(format!("{endpoint}/v1/models")).await;
if let Err(e) = resp {
eprintln!("DS4 endpoint unreachable: {e}"); // connection refused / auth / TLS detail
} Try / catch
match probe_result {
Err(e) if e.is_connect() => eprintln!("start the DS4 server first"),
Err(e) if e.status() == Some(401) => eprintln!("check DS4 API key"),
Err(e) => eprintln!("DS4 probe failed: {e}"),
Ok(_) => {},
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- DS4 /v1/models returned HTTP
- DS4 /v1/models at did not list configured alias ' '…
- DS4 /v1/models could not be reached at
- DS4 /v1/models timed out after 15 seconds at
- Anthropic API error (HTTP )
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/72d68067526e478f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/doctor.rs:579
}
/// Probe DS4 through its cheap `/v1/models` contract instead of waking the
/// model for a completion. The selected model must be advertised.
pub(crate) async fn probe_ds4_models(config: &crate::config::Config) -> anyhow::Result<()> {
use crate::client::DeepSeekClient;
use crate::core::model_client::ModelClient;
let endpoint = crate::client::redact_url_for_display(&config.deepseek_base_url());
let client = DeepSeekClient::new(config)?;
let configured_alias = client.model().to_string();
let models = match tokio::time::timeout(
std::time::Duration::from_secs(15),
client.list_models(),
)
.await
{
Ok(Ok(models)) => models,
Ok(Err(error)) => anyhow::bail!(ds4_probe_error(config, &error.to_string())),
Err(_) => anyhow::bail!("DS4 /v1/models timed out after 15 seconds at {}", endpoint),
};
if !models
.iter()
.any(|available| available.id == configured_alias)
{
let advertised = models
.iter()
.take(8)
.map(|available| available.id.as_str())
.collect::<Vec<_>>()
.join(", ");
anyhow::bail!(
"DS4 /v1/models at {} did not list configured alias '{configured_alias}' (advertised: {})",
endpoint,
if advertised.is_empty() {
"none"
} else {View on GitHub (pinned to 433685b202)