{"record":{"id":"c26ad710825afa94","repo":"windmill-labs/windmill","slug":"git-repos-field-expects-an-array-of-repos","errorCode":null,"errorMessage":"git_repos field expects an array of repos","messagePattern":"git_repos field expects an array of repos","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-yaml/src/lib.rs","lineNumber":574,"sourceCode":"                        return Err(anyhow!(\"Vault ID field expects an array of strings in the format: `label@filename`\"));\n                    };\n\n                    for f in filenames {\n                        let Yaml::String(filename) = f else {\n                            return Err(anyhow!(\"The elements of the vault_id field should be strings in the format: `label@filename`\"));\n                        };\n                        validate_vault_id(filename)?;\n                        ret.vault_id.push(filename.to_string());\n                    }\n                }\n                Yaml::String(key) if key == \"options\" => {\n                    if let Yaml::Array(opts) = &value {\n                        ret.options = parse_ansible_options(opts);\n                    }\n                }\n                Yaml::String(key) if key == \"git_repos\" => {\n                    let Yaml::Array(repos) = &value else {\n                        return Err(anyhow!(\"git_repos field expects an array of repos\"));\n                    };\n\n                    for r in repos {\n                        ret.git_repos.push(\n                            parse_git_repo(r)\n                                .map_err(|e| anyhow!(\"Failed to parse git repo: {e}\"))?,\n                        );\n                    }\n                }\n                Yaml::String(key) if key == \"git_ssh_identity\" => {\n                    extract_ssh_identity(&value, &mut ret.git_ssh_identity)?;\n                }\n                Yaml::String(key) if key == \"delegate_to_git_repo\" => {} // Skip this because it was already parsed before\n                Yaml::String(key) => logs.push_str(&format!(\"\\nUnknown field `{}`. Ignoring\", key)),\n                _ => (),\n            }\n        }\n    }","sourceCodeStart":556,"sourceCodeEnd":592,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-yaml/src/lib.rs#L556-L592","documentation":"This error is thrown by Windmill's YAML ansible-playbook parser when a `git_repos` key inside an ansible requirement's `delegate_to_git_repo`/reqs section is present but its value is not a YAML array (sequence). The parser expects a list of repo maps that it will convert into GitRepo entries for cloning before the playbook runs. Any non-array value (map, string, scalar) fails the `Yaml::Array` destructuring and aborts parsing with this message.","triggerScenarios":"Calling parse_ansible_reqs (via parse_assets or the parser asset pipeline) on a YAML playbook asset where the `git_repos` field is written as a map, a single repo object without list brackets, a string, or a null instead of a YAML sequence of repo maps.","commonSituations":"Indentation mistakes that flatten a list into a single mapping; writing `git_repos: url: ...` (one repo inline) instead of `git_repos:` followed by `- url: ...`; templating tools emitting a dict where a list is expected; copy-pasting a single repo config from another tool.","solutions":["Wrap the git_repos value in a YAML sequence: each repo becomes a `- url: ...` list item","Ensure correct indentation so `git_repos:` is a key whose children are list items, not a nested map","If only one repo is needed, still use a one-element list","Validate the YAML structure locally (e.g. serde_yaml/yaml-lint) before deploying the asset"],"exampleFix":"# before\ngit_repos:\n  url: https://github.com/org/repo.git\n  target: repo\n\n# after\ngit_repos:\n  - url: https://github.com/org/repo.git\n    target: repo","handlingStrategy":"validation","validationCode":"fn validate_git_repos(value: &serde_yaml::Value) -> Result<(), String> {\n    match value.get(\"git_repos\") {\n        None => Ok(()),\n        Some(v) => match v {\n            serde_yaml::Value::Sequence(_) => Ok(()),\n            other => Err(format!(\"git_repos must be a list, got: {:?}\", other)),\n        },\n    }\n}","typeGuard":"fn is_yaml_array(v: &Yaml) -> bool {\n    matches!(v, Yaml::Array(_))\n}","tryCatchPattern":null,"preventionTips":["Always write git_repos as a YAML sequence, even with a single repo","Run a YAML linter/structure check on playbook assets before deploying","Keep `git_repos:` children indented with `-` list markers"],"tags":["yaml","ansible","parser","validation"],"backgroundTag":"yaml-schema-validation","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"}