windmill-labs/windmill · error
git_repos field expects an array of repos
Error message
git_repos field expects an array of repos
What it means
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.
Source
Thrown at backend/parsers/windmill-parser-yaml/src/lib.rs:574
return Err(anyhow!("Vault ID field expects an array of strings in the format: `label@filename`"));
};
for f in filenames {
let Yaml::String(filename) = f else {
return Err(anyhow!("The elements of the vault_id field should be strings in the format: `label@filename`"));
};
validate_vault_id(filename)?;
ret.vault_id.push(filename.to_string());
}
}
Yaml::String(key) if key == "options" => {
if let Yaml::Array(opts) = &value {
ret.options = parse_ansible_options(opts);
}
}
Yaml::String(key) if key == "git_repos" => {
let Yaml::Array(repos) = &value else {
return Err(anyhow!("git_repos field expects an array of repos"));
};
for r in repos {
ret.git_repos.push(
parse_git_repo(r)
.map_err(|e| anyhow!("Failed to parse git repo: {e}"))?,
);
}
}
Yaml::String(key) if key == "git_ssh_identity" => {
extract_ssh_identity(&value, &mut ret.git_ssh_identity)?;
}
Yaml::String(key) if key == "delegate_to_git_repo" => {} // Skip this because it was already parsed before
Yaml::String(key) => logs.push_str(&format!("\nUnknown field `{}`. Ignoring", key)),
_ => (),
}
}
}View on GitHub (pinned to e474e8803c)
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
Example fix
# before
git_repos:
url: https://github.com/org/repo.git
target: repo
# after
git_repos:
- url: https://github.com/org/repo.git
target: repo Defensive patterns
Strategy: validation
Validate before calling
fn validate_git_repos(value: &serde_yaml::Value) -> Result<(), String> {
match value.get("git_repos") {
None => Ok(()),
Some(v) => match v {
serde_yaml::Value::Sequence(_) => Ok(()),
other => Err(format!("git_repos must be a list, got: {:?}", other)),
},
}
} Type guard
fn is_yaml_array(v: &Yaml) -> bool {
matches!(v, Yaml::Array(_))
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to parse git repo: {e}
- git_ssh_identity expects an array of windmill variables (or
- Git ssh identity file must be a string path to a Windmill va
- Should be a Map
- Expected `url` field
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/c26ad710825afa94.
Report an issue: GitHub.