windmill-labs/windmill · error

Failed to parse inventory arg: {}

Error message

Failed to parse inventory arg: {}

What it means

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.

Source

Thrown at backend/windmill-worker/src/ansible_executor.rs:2260

    for inventory in &r.inventories {
        let content;
        if let Some(resource_path) = &inventory.pinned_resource {
            content = client
                .get_resource_value_interpolated::<serde_json::Value>(
                    resource_path,
                    Some(job_id.to_string()),
                )
                .await?;
        } else {
            let o = args
                .as_ref()
                .and_then(|g| g.get(&inventory.name))
                .ok_or(anyhow!(
                    "Specified inventory was missing in the script arguments"
                ))?;

            content = serde_json::from_str(o.get())
                .map_err(|e| anyhow!("Failed to parse inventory arg: {}", e))?;

            if content == serde_json::value::Value::Null {
                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."))?;
            }
        }

        let validated_path = write_file_at_user_defined_location(
            job_dir,
            &inventory.name,
            content
                .get("content")
                .and_then(|v| v.as_str())
                .ok_or(anyhow!(
                    "Invalid inventory resource, `content` field absent or invalid"
                ))?,
            None,
        )
        .map_err(|e| anyhow!("Couldn't write inventory: {}", e))?;

View on GitHub (pinned to e474e8803c)

Solutions

  1. Convert the inventory to JSON (JSON array-of-groups or object form) — e.g. `{"web": {"hosts": ["host1"]}}`.
  2. If you have INI/YAML inventory, keep it as the `content` of an inventory resource instead, or translate it to JSON.
  3. Validate the JSON with `jq .` before passing it.
  4. Check the interpolating step isn't injecting unquoted non-JSON text.

Example fix

// before (INI, invalid JSON)
--data '{"inv": "[web]\nhost1 ansible_host=10.0.0.1"}'
// after (JSON)
--data '{"inv": "{\"web\": {\"hosts\": [\"host1\"], \"vars\": {\"ansible_host\": \"10.0.0.1\"}}}"}'
Defensive patterns

Strategy: validation

Validate before calling

try { JSON.parse(inventoryArg); } catch (e) { throw new Error('inventory arg must be valid JSON: ' + e.message); }

Type guard

function isValidJsonInventory(s) {
  if (typeof s !== 'string') return false;
  try { const v = JSON.parse(s); return v !== null && typeof v === 'object'; } catch { return false; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


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