{"record":{"id":"9928f4a9632cd7ff","repo":"windmill-labs/windmill","slug":"failed-to-read-result","errorCode":null,"errorMessage":"Failed to read result: {}","messagePattern":"Failed to read result: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/common.rs","lineNumber":492,"sourceCode":"pub async fn read_and_check_file(path: &str) -> error::Result<Box<RawValue>> {\n    let content = read_file_content(path).await?;\n\n    check_result_too_big(content.len())?;\n\n    let raw_value: Box<RawValue> =\n        serde_json::from_str(&content).map_err(|e| anyhow!(\"{} is not valid json: {}\", path, e))?;\n    Ok(raw_value)\n}\n\n/// Use this to read `result.json` that were user-generated\npub async fn read_and_check_result(job_dir: &str) -> error::Result<Box<RawValue>> {\n    let result_path = format!(\"{job_dir}/result.json\");\n\n    if let Ok(metadata) = tokio::fs::metadata(&result_path).await {\n        if metadata.len() > 0 {\n            return read_and_check_file(&result_path)\n                .await\n                .map_err(|e| anyhow!(\"Failed to read result: {}\", e).into());\n        }\n    }\n    Ok(to_raw_value(&json!(\"null\")))\n}\n\npub fn capitalize(s: &str) -> String {\n    let mut c = s.chars();\n    match c.next() {\n        None => String::new(),\n        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),\n    }\n}\n\n#[tracing::instrument(level = \"trace\", skip_all)]\npub async fn get_reserved_variables(\n    job: &MiniPulledJob,\n    token: &str,\n    db: &Connection,","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/common.rs#L474-L510","documentation":"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.","triggerScenarios":"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.","commonSituations":"Ansible playbook callback wrote malformed JSON to result.json; result larger than the configured max result size; permissions damaged by the sandbox.","solutions":["Look at the inner error (same message chain) — fix invalid JSON or reduce result size accordingly","If it's a size problem, return less data or raise the result-size limit on the instance","Check file permissions/ownership of job_dir after nsjail execution","If null result is acceptable, ensure the playbook/script doesn't create a broken result.json"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const res = await workerReadResult(jobDir);\n} catch (e) {\n  if (String(e.message).startsWith('Failed to read result')) {\n    console.warn('result.json unreadable; treating as null', e.cause ?? e);\n    return null;\n  }\n  throw e;\n}","preventionTips":["Ensure playbooks/scripts emit valid JSON or no result.json at all","Cap result payload size","Check job_dir permissions after sandboxed execution"],"tags":["json","result-parsing","ansible"],"backgroundTag":"invalid-json-output","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}