BoundaryML/baml · error

No upload URL provided when should_upload is true

Error message

No upload URL provided when should_upload is true

What it means

Raised in process_baml_src_upload_impl (called by process_baml_src_upload) when the server's check response indicates should_upload is true but omits the upload_url field. The publisher uploads the BAML source AST to S3 during trace publishing, and it cannot proceed without a pre-signed upload URL. This indicates the BAML API responded successfully but returned an inconsistent/incomplete payload.

Solutions

  1. Update the BAML runtime and BAML cloud/gateway to compatible versions.
  2. Check whether a proxy/gateway is modifying the API response.
  3. Capture and report the raw check response body to BAML support.
  4. Retry the publish; if persistent, disable baml_src upload via trace config.

Example fix

// before
let upload_url = check_response.upload_url.unwrap();
// after
let upload_url = check_response.upload_url.ok_or_else(|| {
    anyhow::anyhow!("No upload URL provided when should_upload is true")
})?;
Defensive patterns

Strategy: try-catch

Validate before calling

# sanity-check the check response before upload
resp = requests.post(f"{BAML_URL}/v1/baml-src/check", headers=auth, json=req)
data = resp.json()
if data.get("should_upload") and not data.get("upload_url"):
    raise RuntimeError("server said should_upload but returned no upload_url")

Type guard

def has_upload_target(resp) -> bool:
    return not resp.should_upload or (resp.upload_url is not None and resp.upload_metadata is not None)

Try / catch

match process_baml_src_upload().await {
    Err(e) if e.to_string().contains("No upload URL") => {
        log::warn!("collector returned inconsistent check response; skipping src upload");
    }
    Err(e) => return Err(e),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: The collector's upload-check response has should_upload=true but upload_url=None — server bug, schema drift between client and server, or a proxy stripping/mangling JSON fields in the response.

Common situations: Version mismatch between the BAML runtime client and the BAML cloud API, self-hosted gateway returning an older response shape, or an intermediary proxy altering the JSON body.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at engine/baml-runtime/src/tracingv2/publisher/publisher.rs:643

        {
            Ok(response) => response,
            Err(e) => {
                tracing::warn!("Failed to check BAML source upload status: {}", e);
                return Err(e.into());
            }
        };
        tracing::debug!("check_response={:?}", check_response);

        if !check_response.should_upload {
            tracing::debug!("BAML source already uploaded, skipping");
            return Ok(());
        }

        tracing::debug!("Uploading BAML source");

        let upload_url = check_response
            .upload_url
            .ok_or_else(|| anyhow::anyhow!("No upload URL provided when should_upload is true"))?;

        let upload_metadata = check_response.upload_metadata.ok_or_else(|| {
            anyhow::anyhow!("No upload metadata provided when should_upload is true")
        })?;

        // Create the upload payload
        let payload = BamlSrcUploadS3File { ast: ast_obj };

        // Upload to S3
        lookup
            .client
            .put(upload_url)
            .json(&payload)
            .headers({
                let mut headers = reqwest::header::HeaderMap::new();
                for (key, value) in upload_metadata.to_map() {
                    let header_name = format!("x-amz-meta-{key}");
                    if let (Ok(name), Ok(val)) = (

View on GitHub (pinned to bd85ce9dee)