windmill-labs/windmill · error
{} is not valid json: {}
Error message
{} is not valid json: {} What it means
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.
Source
Thrown at backend/windmill-worker/src/common.rs:480
}
/// Read the `result.json` file. This function assumes that the file contains valid json and will
/// result in undefined behaviour if it isn't. If the result.json is user generated or otherwise
/// not guaranteed to be valid, use `read_and_check_result`
pub async fn read_result(
job_dir: &str,
result_stream: Option<String>,
) -> error::Result<Box<RawValue>> {
let rf = read_file(&format!("{job_dir}/result.json")).await;
merge_result_stream(rf, result_stream).await
}
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 {View on GitHub (pinned to e474e8803c)
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
Example fix
// before
result.json: {"result": 42,}
// after
result.json: {"result": 42} Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
const raw = fs.readFileSync('result.json', 'utf8');
JSON.parse(raw); // throws early with position info if malformed Type guard
function isValidJson(s: string): boolean {
try { JSON.parse(s); return true; } catch { return false; }
} Try / catch
try {
const result = await runScriptAndGetResult();
} catch (e) {
if (String(e.message).match(/is not valid json/)) {
// inspect result.json at the reported line/column and fix the writer
}
throw e;
} Prevention
- Serialize results with a JSON encoder, never string concatenation
- Write result.json atomically (temp + rename)
- Keep results under the configured size limit
When it happens
Trigger: 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.
Common situations: User scripts writing partial/pretty-but-invalid JSON on crash; program output redirected straight to result.json; concurrent write truncated by job cancellation.
Related errors
- Invalid JSON for ${field}: ${errorMessage}
- Invalid JSON after replacement: ${message}
- Invalid JSON for ${field}: ${message}${hint}
- Invalid JSON after replacement: ${message}
- Failed to parse or apply JSON: ${error instanceof Error ? er
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/235e191af17681f0.
Report an issue: GitHub.