windmill-labs/windmill · error
Couldn't write inventory: {}
Error message
Couldn't write inventory: {} What it means
write_file_at_user_defined_location failed while persisting the inventory file into the job directory; the executor wraps the io/path error with this message. Failure here usually means the filename derived from inventory.name is unusable (illegal characters, too long) or a filesystem-level error occurred in the job dir.
Source
Thrown at backend/windmill-worker/src/ansible_executor.rs:2278
.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))?;
nsjail_mounts.push(
define_nsjail_mount(job_dir, &validated_path)
.map_err(|e| anyhow!("Inventory path (a.k.a. `name`) is invalid: {}", e))?,
);
logs.push_str(&format!("\nCreated inventory `{}`", inventory.name));
}
for file_res in &r.file_resources {
let r =
get_resource_or_variable_content(client, &file_res.resource_path, job_id.to_string())
.await?;
let path = file_res.target_path.clone();
let validated_path =
write_file_at_user_defined_location(job_dir, path.as_str(), &r, file_res.mode)
.map_err(|e| anyhow!("Couldn't write text file at {}: {}", path, e))?;
View on GitHub (pinned to e474e8803c)
Solutions
- Rename the inventory `name` in the yaml to a simple filesystem-safe identifier (letters, digits, `-`, `_`).
- Check worker disk space (`df` on the job/tmp dir) and permissions of the job directory.
- Look at the inner error in this message to distinguish path validation vs I/O failure.
- Retry the job once disk/permission issues are fixed.
Example fix
// before
inventory: { name: "prod/web servers" }
// after
inventory: { name: "prod-web-servers" } Defensive patterns
Strategy: validation
Validate before calling
function isFilenameSafe(name) {
return /^[A-Za-z0-9._-]+$/.test(name) && !name.includes('..');
}
if (!isFilenameSafe(inventoryName)) throw new Error('inventory name must be a flat safe filename'); Type guard
function isSafeFilename(s) { return typeof s === 'string' && /^[A-Za-z0-9._-]{1,128}$/.test(s); } Try / catch
// surface the inner io error and fail fast
match write_inventory().await {
Err(e) if e.to_string().contains("Couldn't write inventory") => bail!("check worker disk space and inventory name: {e}"),
other => other,
} Prevention
- Use letters/digits/`-`/`_` for inventory names; avoid spaces, slashes, unicode.
- Keep names short (filesystem 255-byte filename limit).
- Monitor worker tmp/disk usage; full disks break job dir writes.
- Retry after transient disk/permission fixes.
When it happens
Trigger: create_file_resources calls write_file_at_user_defined_location(job_dir, &inventory.name, content, None) and it errors — bad path chars in `inventory.name` (slashes, `..`), permission issues on the worker's temp dir, or disk full — via handle_ansible_job.
Common situations: Inventory name containing `/`, spaces, or unusual unicode; name exceeding filesystem filename limits; worker tmpfs full; read-only job directory after a mount misconfiguration.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Directory '{}' already exists and is not empty
- Invalid inventory definition
- Specified inventory was missing in the script arguments
- Failed to parse inventory arg: {}
- The inventory argument was left empty. If you do not wish to
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/1faac971b8739919.
Report an issue: GitHub.