Hmbown/CodeWhale · error

the sandbox id is not a usable path token

Error message

the sandbox id is not a usable path token

What it means

Before interpolating a sandbox id into control-plane or toolbox URL paths, valid_sandbox_id requires a non-empty token of at most 128 chars made of URL-path-safe characters. If the provider (or a stale receipt) returned an id that fails this check, toolbox_base refuses to build a URL rather than risk path injection or a malformed request.

Solutions

  1. Inspect receipt.sandbox_id — re-create the sandbox so a fresh, provider-issued id replaces the stale one.
  2. Trim/sanitize the id at the boundary where receipts are produced, or reject it earlier with your own check matching valid_sandbox_id's rules (non-empty, <=128 chars, path-safe).
  3. If the provider's ids changed format, update the integration rather than bypassing the check.

Example fix

// before
let base = toolbox_base(&receipt)?; // bail on odd id
// after
fn is_path_safe(id: &str) -> bool {
    !id.is_empty() && id.len() <= 128 && id.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '_'))
}
anyhow::ensure!(is_path_safe(&receipt.sandbox_id), "sandbox id invalid: {:?}", receipt.sandbox_id);
let base = toolbox_base(&receipt)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_path_safe(id: &str) -> bool {
    !id.is_empty() && id.len() <= 128 && id.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '_'))
}
// before calling any path-building API:
anyhow::ensure!(is_path_safe(&receipt.sandbox_id), "bad sandbox id");

Type guard

fn usable_sandbox_id(id: &str) -> Option<&str> {
    if !id.is_empty() && id.len() <= 128 && id.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '_')) { Some(id) } else { None }
}

Try / catch

match toolbox_base(&receipt) {
    Err(e) if e.to_string().contains("not a usable path token") => eprintln!("stale or malformed sandbox id: {:?}", receipt.sandbox_id),
    other => other?,
}

Prevention

When it happens

Trigger: Calling toolbox_base (or any path built from SandboxReceipt.sandbox_id) with a receipt whose sandbox_id is empty, longer than 128 chars, or contains characters like '/', '?', '#', or whitespace.

Common situations: A provider API change altering id format; a stale/corrupted receipt loaded from state; a mock or fake sandbox id used in tests carrying path-special characters.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/aeebeb339bebd343. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/cloud_dispatch.rs:1421

    /// declared `HARNESS_TIMEOUT_SECS`.
    pub(crate) fn harness_client_budget_secs(command: &HarnessCommand) -> u64 {
        u64::from(command.timeout_secs).saturating_add(Self::HARNESS_CLIENT_SLACK_SECS)
    }

    fn api_key() -> Result<String> {
        read_api_key().ok_or_else(|| anyhow!(missing_credentials_message()))
    }

    /// Control-plane URL under the validated base.
    fn control_plane_url(path: &str) -> Result<reqwest::Url> {
        let base = validate_outbound_origin(&daytona_api_url())?;
        join_api_path(base, path).context("failed to build the cloud agent request URL")
    }

    /// Toolbox base for one sandbox: `{toolboxProxyUrl}/{sandboxId}`.
    fn toolbox_base(receipt: &SandboxReceipt) -> Result<reqwest::Url> {
        if !valid_sandbox_id(&receipt.sandbox_id) {
            bail!("the sandbox id is not a usable path token");
        }
        let fallback = format!("{}/toolbox", DEFAULT_DAYTONA_API);
        let raw = receipt.toolbox_url.as_deref().unwrap_or(&fallback);
        let base = validate_outbound_origin(raw)?;
        join_api_path(base, &receipt.sandbox_id).context("failed to build the sandbox toolbox URL")
    }

    /// Apply the dispatch labels via Daytona's dedicated labels endpoint.
    fn put_sandbox_labels(sandbox_id: &str, api_key: &str, job: &CloudJob) -> Result<()> {
        if !valid_sandbox_id(sandbox_id) {
            bail!("the sandbox id is not a usable path token");
        }
        let url = Self::control_plane_url(&format!("sandbox/{sandbox_id}/labels"))?;
        let body = serde_json::json!({
            "labels": {
                SANDBOX_JOB_LABEL: job.id,
                "codewhale.forge": job.forge.as_str(),
                SANDBOX_PRODUCT_LABEL: SANDBOX_PRODUCT_VALUE,

View on GitHub (pinned to 73e0f67d83)