{"record":{"id":"e5f99c63eaf7e98d","repo":"windmill-labs/windmill","slug":"error-getting-ansible-collection-versions-stderr","errorCode":null,"errorMessage":"Error getting ansible collection versions: {stderr}","messagePattern":"Error getting ansible collection versions: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/ansible_executor.rs","lineNumber":1084,"sourceCode":"}\n\npub async fn get_collection_locks(\n    job_dir: &str,\n) -> anyhow::Result<(HashMap<String, String>, String)> {\n    let mut ansible_cmd = Command::new(ANSIBLE_GALAXY_PATH.as_str());\n\n    ansible_cmd\n        .current_dir(job_dir)\n        .args([\"collection\", \"list\", \"--format\", \"json\", \"-p\", \"./\"]);\n\n    let output = ansible_cmd.output().await?;\n\n    let mut ret = HashMap::new();\n    let mut logs = String::new();\n\n    if !output.status.success() {\n        let stderr = String::from_utf8(output.stderr)?;\n        return Err(anyhow!(\n            \"Error getting ansible collection versions: {stderr}\"\n        ));\n    }\n\n    let stdout = String::from_utf8(output.stdout)?;\n\n    let val: serde_json::Value = serde_json::from_str(&stdout)?;\n\n    let Some(own_collections) = val.get(format!(\"{}/ansible_collections\", job_dir)) else {\n        return Ok((ret, logs));\n    };\n\n    let collections = own_collections.as_object().ok_or(anyhow!(\n        \"Expected an object (map) for the `ansible-galaxy collection list` command output and got {}\",\n        own_collections\n    ))?;\n\n    for (c_name, c) in collections.iter() {","sourceCodeStart":1066,"sourceCodeEnd":1102,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/ansible_executor.rs#L1066-L1102","documentation":"Windmill's ansible dependency-locking step runs `ansible-galaxy collection list` and requires it to exit successfully. When the process returns a non-zero status, the worker aborts and surfaces the process stderr verbatim so the underlying ansible failure is visible. It is thrown from get_collection_locks while computing dependency locks for an ansible job.","triggerScenarios":"Running an ansible script/job whose dependency-lock phase invokes `ansible-galaxy collection list` in the job directory and the command exits non-zero (bad install, broken ansible install, unreadable collections dir, invalid ansible.cfg).","commonSituations":"ansible/ansible-galaxy not installed or not on PATH in the worker image; a partially-failed `ansible-galaxy collection install` left a corrupt collections directory; an invalid ansible.cfg in the job dir; incompatible ansible-core version whose CLI flags changed.","solutions":["Read the stderr embedded in the message and fix the underlying ansible-galaxy failure it reports.","Verify ansible/ansible-core is installed in the worker image (`ansible-galaxy --version`) and on PATH.","Delete/clean the job's collection directory and re-run the collection install step.","Check for a malformed ansible.cfg in the workspace/job directory.","Pin a compatible ansible-core version if a recent upgrade changed CLI behavior."],"exampleFix":"// Dockerfile of worker image\n// before\nRUN pip install ansible-runner\n// after\nRUN pip install ansible-core ansible-runner && ansible-galaxy --version","handlingStrategy":"validation","validationCode":"// before running the job, on the worker:\nansible-galaxy --version || echo 'ansible-galaxy missing or broken'\nansible-galaxy collection list >/dev/null 2>&1 && echo OK || echo 'collection list fails; fix ansible install'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Bake ansible-core into the worker image and smoke-test ansible-galaxy at build time","Keep ansible-core version pinned and compatible with the Windmill worker","Clean corrupted collection directories instead of retrying blindly","Check ansible.cfg validity in workspace repos"],"tags":["ansible","subprocess","dependency-locking"],"backgroundTag":"subprocess-nonzero-exit","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"}