{"record":{"id":"235e191af17681f0","repo":"windmill-labs/windmill","slug":"is-not-valid-json","errorCode":null,"errorMessage":"{} is not valid json: {}","messagePattern":"(.+?) is not valid json: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/common.rs","lineNumber":480,"sourceCode":"}\n/// Read the `result.json` file. This function assumes that the file contains valid json and will\n/// result in undefined behaviour if it isn't. If the result.json is user generated or otherwise\n/// not guaranteed to be valid, use `read_and_check_result`\npub async fn read_result(\n    job_dir: &str,\n    result_stream: Option<String>,\n) -> error::Result<Box<RawValue>> {\n    let rf = read_file(&format!(\"{job_dir}/result.json\")).await;\n    merge_result_stream(rf, result_stream).await\n}\n\npub 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 {","sourceCodeStart":462,"sourceCodeEnd":498,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/common.rs#L462-L498","documentation":"read_and_check_file reads a JSON file from the job directory (usually a worker-produced output like result.json) and enforces the result-size limit. If the file content is not valid JSON, serde_json's parse error is wrapped in this message.","triggerScenarios":"A script writes result.json (or another file read via this helper) containing malformed JSON — e.g. trailing commas, truncated writes, or raw text output instead of JSON.","commonSituations":"User scripts writing partial/pretty-but-invalid JSON on crash; program output redirected straight to result.json; concurrent write truncated by job cancellation.","solutions":["Inspect the wrapped serde error (line/column) and fix the producing script to emit valid JSON","Ensure the script serializes output with a JSON encoder (json.dumps / JSON.stringify) rather than raw print","Check the file wasn't truncated (disk full, kill -9 mid-write); write atomically via temp file + rename","If the file is intentionally non-JSON, don't place it where Windmill reads it as a result"],"exampleFix":"// before\nresult.json: {\"result\": 42,}\n// after\nresult.json: {\"result\": 42}","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst raw = fs.readFileSync('result.json', 'utf8');\nJSON.parse(raw); // throws early with position info if malformed","typeGuard":"function isValidJson(s: string): boolean {\n  try { JSON.parse(s); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  const result = await runScriptAndGetResult();\n} catch (e) {\n  if (String(e.message).match(/is not valid json/)) {\n    // inspect result.json at the reported line/column and fix the writer\n  }\n  throw e;\n}","preventionTips":["Serialize results with a JSON encoder, never string concatenation","Write result.json atomically (temp + rename)","Keep results under the configured size limit"],"tags":["json","parsing","filesystem"],"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"}