Hmbown/CodeWhale · error · anyhow::Error

runtime API returned {status}

Error message

runtime API returned {status}

What it means

SessionManager normalizes its managed (sessions) directory before use: normalize_managed_dir rejects an empty path immediately with InvalidInput - an empty OsString cannot name a directory - then rejects relative paths containing traversal components, and finally anchors plain relative paths to the current directory.

Source

Thrown at crates/app-server/src/lib.rs:1109

            }
        }
    }

    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?;
        let status = response.status();
        let body = response.text().await?;
        if !status.is_success() {
            let detail = body.trim();
            if detail.is_empty() {
                bail!("runtime API returned {status}");
            }
            bail!("runtime API returned {status}: {detail}");
        }
        serde_json::from_str(&body).with_context(|| format!("invalid runtime API json: {body}"))
    }

    async fn ensure_runtime_thread(
        &mut self,
        stdio_thread_id: &str,
        hint: Option<RuntimeThreadHint>,
    ) -> Result<String> {
        if let Some(runtime_thread_id) = self.thread_map.get(stdio_thread_id) {
            return Ok(runtime_thread_id.clone());
        }
        let hint = hint.unwrap_or_default();
        let runtime_thread_id = self
            .create_runtime_thread(hint.model, hint.workspace)
            .await?;

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Set sessions_dir to a real path, or remove the empty override so the built-in default applies
  2. Replace unwrap_or_default() with unwrap_or_else(default_sessions_dir) for optional path settings
  3. Validate path-valued config at load time and reject blank strings with a clear field name

Example fix

// before
let dir = cfg.sessions_dir.clone().unwrap_or_default();

// after
let dir = cfg.sessions_dir.clone().unwrap_or_else(default_sessions_dir);
Defensive patterns

Strategy: validation

Validate before calling

fn managed_dir_is_valid(p: &std::path::Path) -> bool {
    !p.as_os_str().is_empty()
}

Type guard

fn is_non_empty_dir_path(p: &std::path::Path) -> bool { !p.as_os_str().is_empty() }

Try / catch

match normalize_managed_dir(dir.clone()) {
    Err(e) if e.to_string().contains("cannot be empty") => {
        // fail config load naming the sessions_dir field; require a real path or the default
    }
    other => other?,
}

Prevention

When it happens

Trigger: Constructing SessionManager (which calls normalize_managed_dir at session_manager.rs:1022) with an empty sessions_dir PathBuf: a config value like sessions_dir = "", a blank environment override, or Option::unwrap_or_default() on a missing setting (PathBuf's default is empty).

Common situations: Config templating that leaves a path key present but blank; env var set to an empty string; code defaulting a missing optional path to PathBuf::new() instead of a real default directory.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/dcefd1caf719c807. Report an issue: GitHub.