{"record":{"id":"6a44c90a95dbccf1","repo":"windmill-labs/windmill","slug":"error-updating-role-versions-e","errorCode":null,"errorMessage":"Error updating role versions: {e}","messagePattern":"Error updating role versions: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-yaml/src/lib.rs","lineNumber":927,"sourceCode":"    }\n\n    Ok(logs)\n}\n\npub fn add_versions_to_requirements_yaml(\n    input: &str,\n    role_versions: &HashMap<String, String>,\n    collection_versions: &HashMap<String, String>,\n) -> anyhow::Result<(String, String)> {\n    let mut docs =\n        YamlLoader::load_from_str(input).map_err(|e| anyhow!(\"YAML parse error: {}\", e))?;\n    let doc = &mut docs[0];\n\n    let mut logs = String::new();\n\n    logs.push_str(\n        &update_versions(\"roles\", doc, role_versions)\n            .map_err(|e| anyhow!(\"Error updating role versions: {e}\"))?,\n    );\n    logs.push_str(\n        &update_versions(\"collections\", doc, collection_versions)\n            .map_err(|e| anyhow!(\"Error updating collection versions: {e}\"))?,\n    );\n\n    if !logs.is_empty() {\n        logs.push_str(\"WARNING: You might want to try adding manual versions for these, otherwise there could be breaking changes on deployed scripts\\n\");\n    }\n\n    let mut out_str = String::new();\n    {\n        let mut emitter = YamlEmitter::new(&mut out_str);\n        emitter\n            .dump(doc)\n            .map_err(|e| anyhow!(\"YAML emit error: {}\", e))?;\n    }\n","sourceCodeStart":909,"sourceCodeEnd":945,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-yaml/src/lib.rs#L909-L945","documentation":"add_versions_to_requirements_yaml pins versions for the `roles` section first via update_versions, and wraps any inner failure with the prefix 'Error updating role versions:'. The inner cause is one of the update_versions errors (root not a map, element not a map, missing `name`). This wrapper identifies the failing section as roles.","triggerScenarios":"Calling add_versions_to_requirements_yaml on a requirements file whose roles section is structurally invalid: the doc root is not a map, a role entry is a bare string, or an entry lacks a string `name`.","commonSituations":"Legacy top-level-list requirements files; short-form role entries (`- geerlingguy.docker`); role entries using `src` instead of `name`; empty roles sections whose doc is otherwise a scalar.","solutions":["Read the wrapped inner message after the prefix to identify the structural problem.","Ensure the document root is a map and `roles:` is a list of {name, ...} maps.","Convert short-form or src-based role entries to `name:`-based maps.","Validate the YAML structure before deploying."],"exampleFix":"# before\n- src: geerlingguy.docker\n# after\nroles:\n  - name: geerlingguy.docker","handlingStrategy":"validation","validationCode":"fn validate_roles(input: &str) -> Result<(), String> {\n    let doc: serde_yaml::Value = serde_yaml::from_str(input).map_err(|e| e.to_string())?;\n    let root = doc.as_mapping().ok_or(\"root must be a map\")?;\n    if let Some(items) = root.get(\"roles\").and_then(|s| s.as_sequence()) {\n        for e in items {\n            if e.get(\"name\").map(|n| n.is_string()) != Some(true) {\n                return Err(\"each role needs a string name\".into());\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":"fn roles_are_pinnable(v: &serde_yaml::Value) -> bool {\n    v.as_mapping().map(|m| m.get(\"roles\").map(|r| r.as_sequence().map(|s| s.iter().all(|e| e.get(\"name\").map(|n| n.is_string()).unwrap_or(false)).unwrap_or(true))).unwrap_or(true)).unwrap_or(false)\n}","tryCatchPattern":"match pin_versions(input, &roles, &collections) {\n    Err(e) if e.to_string().contains(\"Error updating role versions\") => {\n        eprintln!(\"Roles section invalid (see inner message): entries need name fields\\n{e}\");\n    }\n    other => other,\n}","preventionTips":["Ensure the root is a map before calling the pinning API","Every role entry needs a string `name:` field","Convert src-based and short-form role entries to name-based maps","Pre-validate the roles section with serde_yaml before deploying"],"tags":["ansible","requirements","roles","version-pinning"],"backgroundTag":"invalid-dependency-manifest-entry","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"}