windmill-labs/windmill · error
{section} dependency should be a map
Error message
{section} dependency should be a map What it means
add_versions_to_requirements_yaml pins role/collection versions into an Ansible requirements file. update_versions first asserts the top-level parsed YAML document is a mapping. This error is thrown when the requirements YAML root is not a map — e.g. it is a list at the top level, a scalar, or an empty document — so the `roles`/`collections` sections cannot be looked up.
Source
Thrown at backend/parsers/windmill-parser-yaml/src/lib.rs:882
}
Yaml::String(s) => serde_json::Value::String(s.to_string()),
Yaml::Integer(i) => serde_json::Value::Number(i.clone().into()),
Yaml::Real(r) => serde_json::Value::Number(r.parse().unwrap_or(0.into())),
Yaml::Boolean(b) => serde_json::Value::Bool(*b),
Yaml::Null => serde_json::Value::Null,
_ => serde_json::Value::Null,
}
}
fn update_versions(
section: &str,
yaml: &mut Yaml,
versions: &HashMap<String, String>,
) -> anyhow::Result<String> {
let mut logs = String::new();
let Yaml::Hash(ref mut m) = yaml else {
return Err(anyhow!("{section} dependency should be a map"));
};
if let Some(Yaml::Array(elements)) = m.get_mut(&Yaml::String(section.to_string())) {
for el in elements {
let Yaml::Hash(ref mut h) = el else {
return Err(anyhow!("{section} dependency element should be a map"));
};
if let Some(name) = h
.get(&Yaml::String("name".to_string()))
.and_then(|n| n.as_str())
{
if let Some(version) = versions.get(name) {
h.insert(
Yaml::String("version".to_string()),
Yaml::String(version.to_string()),
);
} else {View on GitHub (pinned to e474e8803c)
Solutions
- Restructure the requirements file as a map with `roles:` and `collections:` keys, each holding a list of {name, version} entries.
- If the file is empty, add at least `roles: []` / `collections: []`.
- Convert legacy top-level-list requirements to the modern map format supported by ansible-galaxy 2.10+.
- Validate the parsed root is a mapping before calling the API.
Example fix
# before (legacy top-level list)
- src: geerlingguy.docker
# after
roles:
- name: geerlingguy.docker
version: 6.1.0 Defensive patterns
Strategy: type-guard
Validate before calling
fn validate_requirements_root(input: &str) -> Result<(), String> {
let doc: serde_yaml::Value = serde_yaml::from_str(input).map_err(|e| e.to_string())?;
if doc.as_mapping().is_none() {
return Err("requirements.yml root must be a mapping with roles:/collections: keys".into());
}
Ok(())
} Type guard
fn is_requirements_map(v: &serde_yaml::Value) -> bool {
v.as_mapping().map(|m| m.contains_key("roles") || m.contains_key("collections")).unwrap_or(false)
} Try / catch
match pin_versions(input, &roles, &collections) {
Err(e) if e.to_string().contains("dependency should be a map") => {
eprintln!("requirements.yml root must be a map: roles:\n - name: ...\n{e}");
}
other => other,
} Prevention
- Use the modern requirements format: root map with roles:/collections: keys
- Never ship an empty or legacy top-level-list requirements file to this parser
- Check the parsed root type before calling the API
- Migrate ansible-galaxy <2.10 list-style requirements files
When it happens
Trigger: Calling add_versions_to_requirements_yaml with input whose first YAML document is `[]`, a plain string, or empty; legacy requirements files that are a top-level list (`- src: ...`) rather than `roles:`/`collections:` maps.
Common situations: Old-style ansible-galaxy requirements.yml (pre-2.10) with a top-level sequence of roles; an empty requirements file created by scaffolding; a YAML parse producing a scalar due to bad indentation.
Related errors
- Invalid file resource: Should be a dictionary.
- {section} dependency element should be a map
- {section} dependency element: missing or invalid `name` fiel
- Failed to parse yaml: {}
- Invalid inventory definition
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/d03ed86af5605d99.
Report an issue: GitHub.