Hmbown/CodeWhale · error · anyhow::Error
timed out waiting for runtime API bridge at
Error message
timed out waiting for runtime API bridge at {}/health What it means
The app-server polls the Runtime API bridge's `/health` endpoint every 50 ms until a deadline; if the endpoint never returns a successful response in time, startup fails with this timeout. It means the runtime process did not come up, is listening on a different URL, or is wedged.
Solutions
- Check the runtime process is actually running and listening on base_url (curl the /health endpoint manually).
- Check for port conflicts (`address already in use`) or a wrong port in the runtime configuration.
- Inspect runtime stderr/logs for a startup crash.
- Increase the health-wait deadline if the runtime legitimately takes long to boot.
Defensive patterns
Strategy: retry
Validate before calling
// probe before relying on the bridge
let ok = reqwest::get(format!("{base}/health")).await.ok()
.map(|r| r.status().is_success()).unwrap_or(false);
if !ok { eprintln!("runtime bridge not healthy yet"); } Try / catch
// wrap launch with retry/backoff on timeout
match start_app_server().await {
Err(e) if e.to_string().contains("timed out waiting for runtime API bridge") => {
// inspect runtime logs, then retry once with a longer deadline
}
Err(e) => return Err(e),
Ok(v) => Ok(v),
} Prevention
- Verify the runtime binary path and port in config before launch.
- Check for port conflicts with `ss -ltnp` / `lsof -i :<port>`.
- Capture runtime stderr so startup crashes are visible instead of appearing as health timeouts.
When it happens
Trigger: `wait_for_health`-style polling loop sees non-success HTTP statuses or connection errors from `GET {base_url}/health` until `Instant::now() >= deadline`.
Common situations: Runtime binary fails to start (missing binary, port conflict), slow cold start exceeding the deadline, or base_url misconfigured to the wrong port.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- timed out waiting for runtime API bridge at
- ${compactRuntimeError(response.status, body)}
- ${compactRuntimeError(response.status, body)}
- ${compactRuntimeError(response.status, body)}
- ${compactRuntimeError(response.status, result)}
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/23e266d6b45bc388.
Report an issue: GitHub.
Appendix: source
Thrown at crates/app-server/src/lib.rs:1597
let deadline = Instant::now() + Duration::from_secs(15);
loop {
if let Some(child) = self.child.as_mut()
&& let Some(status) = child.try_wait()?
{
return Err(anyhow!(
"runtime API bridge exited before becoming ready (status {status})"
));
}
match self
.client
.get(format!("{}/health", self.base_url))
.send()
.await
{
Ok(response) if response.status().is_success() => return Ok(()),
_ if Instant::now() >= deadline => {
bail!(
"timed out waiting for runtime API bridge at {}/health",
self.base_url
)
}
_ => tokio::time::sleep(Duration::from_millis(50)).await,
}
}
}
fn authed(&self, builder: reqwest::RequestBuilder) -> reqwest::RequestBuilder {
match self.auth_token.as_deref() {
Some(token) => builder.bearer_auth(token),
None => builder,
}
}
async fn request_json(&self, builder: reqwest::RequestBuilder) -> Result<Value> {
let response = builder.send().await?;View on GitHub (pinned to 73e0f67d83)