windmill-labs/windmill · error

Failed to read result: {}

Error message

Failed to read result: {}

What it means

read_and_check_result reads the job's result.json after execution. If result.json exists and is non-empty but cannot be read/validated (via read_and_check_file), the error is wrapped as 'Failed to read result'. A missing or empty result.json is NOT an error — it returns JSON null.

Source

Thrown at backend/windmill-worker/src/common.rs:492

pub async fn read_and_check_file(path: &str) -> error::Result<Box<RawValue>> {
    let content = read_file_content(path).await?;

    check_result_too_big(content.len())?;

    let raw_value: Box<RawValue> =
        serde_json::from_str(&content).map_err(|e| anyhow!("{} is not valid json: {}", path, e))?;
    Ok(raw_value)
}

/// Use this to read `result.json` that were user-generated
pub async fn read_and_check_result(job_dir: &str) -> error::Result<Box<RawValue>> {
    let result_path = format!("{job_dir}/result.json");

    if let Ok(metadata) = tokio::fs::metadata(&result_path).await {
        if metadata.len() > 0 {
            return read_and_check_file(&result_path)
                .await
                .map_err(|e| anyhow!("Failed to read result: {}", e).into());
        }
    }
    Ok(to_raw_value(&json!("null")))
}

pub fn capitalize(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
    }
}

#[tracing::instrument(level = "trace", skip_all)]
pub async fn get_reserved_variables(
    job: &MiniPulledJob,
    token: &str,
    db: &Connection,

View on GitHub (pinned to e474e8803c)

Solutions

  1. Look at the inner error (same message chain) — fix invalid JSON or reduce result size accordingly
  2. If it's a size problem, return less data or raise the result-size limit on the instance
  3. Check file permissions/ownership of job_dir after nsjail execution
  4. If null result is acceptable, ensure the playbook/script doesn't create a broken result.json
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const res = await workerReadResult(jobDir);
} catch (e) {
  if (String(e.message).startsWith('Failed to read result')) {
    console.warn('result.json unreadable; treating as null', e.cause ?? e);
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: handle_ansible_job finishes and result.json exists non-empty but is unreadable: permission error, invalid JSON, or size over the check_result_too_big limit.

Common situations: Ansible playbook callback wrote malformed JSON to result.json; result larger than the configured max result size; permissions damaged by the sandbox.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/9928f4a9632cd7ff. Report an issue: GitHub.