{"record":{"id":"2991771b1da2d4de","repo":"windmill-labs/windmill","slug":"failed-to-parse-inventory-arg","errorCode":null,"errorMessage":"Failed to parse inventory arg: {}","messagePattern":"Failed to parse inventory arg: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/ansible_executor.rs","lineNumber":2260,"sourceCode":"    for inventory in &r.inventories {\n        let content;\n        if let Some(resource_path) = &inventory.pinned_resource {\n            content = client\n                .get_resource_value_interpolated::<serde_json::Value>(\n                    resource_path,\n                    Some(job_id.to_string()),\n                )\n                .await?;\n        } else {\n            let o = args\n                .as_ref()\n                .and_then(|g| g.get(&inventory.name))\n                .ok_or(anyhow!(\n                    \"Specified inventory was missing in the script arguments\"\n                ))?;\n\n            content = serde_json::from_str(o.get())\n                .map_err(|e| anyhow!(\"Failed to parse inventory arg: {}\", e))?;\n\n            if content == serde_json::value::Value::Null {\n                Err(anyhow!(\"The inventory argument was left empty. If you do not wish to specify an inventory for this script, remove the `inventory:` section from the yaml.\"))?;\n            }\n        }\n\n        let validated_path = write_file_at_user_defined_location(\n            job_dir,\n            &inventory.name,\n            content\n                .get(\"content\")\n                .and_then(|v| v.as_str())\n                .ok_or(anyhow!(\n                    \"Invalid inventory resource, `content` field absent or invalid\"\n                ))?,\n            None,\n        )\n        .map_err(|e| anyhow!(\"Couldn't write inventory: {}\", e))?;","sourceCodeStart":2242,"sourceCodeEnd":2278,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/ansible_executor.rs#L2242-L2278","documentation":"The inventory argument was found in args but its string value is not valid JSON; serde_json::from_str fails and the executor wraps the serde error with this message. Windmill stores inventories as JSON strings, so any non-JSON value passed as the inventory argument triggers this.","triggerScenarios":"Passing the inventory argument as YAML, INI, or plain text (e.g. `[web]\\nhost1 ansible_host=1.2.3.4`) instead of a JSON document, or passing a number/boolean rather than an object/string of JSON, in create_file_resources via handle_ansible_job.","commonSituations":"Users pasting classic INI inventory format into the arg; copy-pasting YAML inventory from ansible docs; a template interpolating non-JSON content; a flow upstream step emitting raw text.","solutions":["Convert the inventory to JSON (JSON array-of-groups or object form) — e.g. `{\"web\": {\"hosts\": [\"host1\"]}}`.","If you have INI/YAML inventory, keep it as the `content` of an inventory resource instead, or translate it to JSON.","Validate the JSON with `jq .` before passing it.","Check the interpolating step isn't injecting unquoted non-JSON text."],"exampleFix":"// before (INI, invalid JSON)\n--data '{\"inv\": \"[web]\\nhost1 ansible_host=10.0.0.1\"}'\n// after (JSON)\n--data '{\"inv\": \"{\\\"web\\\": {\\\"hosts\\\": [\\\"host1\\\"], \\\"vars\\\": {\\\"ansible_host\\\": \\\"10.0.0.1\\\"}}}\"}'","handlingStrategy":"validation","validationCode":"try { JSON.parse(inventoryArg); } catch (e) { throw new Error('inventory arg must be valid JSON: ' + e.message); }","typeGuard":"function isValidJsonInventory(s) {\n  if (typeof s !== 'string') return false;\n  try { const v = JSON.parse(s); return v !== null && typeof v === 'object'; } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Always pass inventories as JSON documents, never INI/YAML text.","Validate with `jq .` or JSON.parse before running the script.","Convert classic ansible inventories to JSON format once, store as a resource.","Check template interpolation isn't injecting non-JSON text."],"tags":["ansible","inventory","json","parse-error"],"backgroundTag":"invalid-json","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"}