BoundaryML/baml · error

Failed to parse JSON response

Error message

Failed to parse JSON response: {e}

What it means

Once a successful response is received, get_playground_dist deserializes the body into serde_json::Value via resp.json(). If the body is not valid JSON (or the content is malformed/HTML), the reqwest/serde error is wrapped with this message. GitHub is expected to return JSON, so this indicates the body was not the expected release payload.

Solutions

  1. Log or capture the raw response body to see what was actually returned (likely HTML from a proxy).
  2. Bypass or correctly configure the corporate proxy so api.github.com returns real JSON (Content-Type: application/json).
  3. Retry the request if the body was truncated by a transient network issue.
  4. Verify the API URL hasn't been redirected to an unexpected host.
Defensive patterns

Strategy: try-catch

Try / catch

// treat non-JSON bodies (proxy pages) as network-layer failure
match get_playground_dist().await {
    Err(e) if e.to_string().contains("Failed to parse JSON response") => {
        eprintln!("Non-JSON body — check proxy/interception");
        fallback_to_bundled_dist();
    }
    other => other?,
}

Prevention

When it happens

Trigger: resp.json::<serde_json::Value>() fails because the response body is not parseable JSON — e.g. a proxy or captive portal returned an HTML error page with a 2xx status, or the body was truncated.

Common situations: Corporate proxy/interception appliance returning HTML with 200 OK; a caching layer serving a corrupt or empty body; misrouted request hitting a non-GitHub endpoint after config changes.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/21b4614815b88e9e. Report an issue: GitHub.

Appendix: source

Thrown at engine/playground-server/src/server.rs:156

    // Check if the response is successful
    if !resp.status().is_success() {
        let status = resp.status();
        let body = resp
            .text()
            .await
            .unwrap_or_else(|_| "Failed to read response body".to_string());
        return Err(anyhow::anyhow!(
            "GitHub API request failed with status {}: {}",
            status,
            body
        ));
    }

    tracing::info!("Parsing JSON response...");
    let release: serde_json::Value = resp
        .json()
        .await
        .map_err(|e| anyhow::anyhow!("Failed to parse JSON response: {e}"))?;

    // Find the main asset
    let assets = release["assets"]
        .as_array()
        .ok_or_else(|| anyhow::anyhow!("No assets in release metadata"))?;
    let asset = assets
        .iter()
        .find(|a| a["name"].as_str() == Some(&web_panel_asset_name))
        .ok_or_else(|| anyhow::anyhow!("No asset named '{}' in release", web_panel_asset_name))?;
    let download_url = asset["browser_download_url"]
        .as_str()
        .ok_or_else(|| anyhow::anyhow!("No download URL for asset"))?;

    // Find the checksum asset
    let checksum_asset = assets
        .iter()
        .find(|a| a["name"].as_str() == Some(&checksum_asset_name))
        .ok_or_else(|| {

View on GitHub (pinned to bd85ce9dee)