windmill-labs/windmill · error

{section} dependency element should be a map

Error message

{section} dependency element should be a map

What it means

Within a `roles` or `collections` section of an Ansible requirements file, each dependency entry must itself be a mapping with a `name` key. update_versions throws this error when an element of the roles/collections array is a scalar, list, or null instead of a hash, so no name/version can be read from it.

Source

Thrown at backend/parsers/windmill-parser-yaml/src/lib.rs:888

        _ => 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 {
                    logs.push_str(&format!("WARNING: {section} dependency `{name}` has no locked version, using the latest or system installed version.\n"));
                }
            } else {
                return Err(anyhow!(
                    "{section} dependency element: missing or invalid `name` field"
                ));

View on GitHub (pinned to e474e8803c)

Solutions

  1. Rewrite every entry as a mapping: `- name: <role-or-collection>` (optionally with `version:`).
  2. Replace short-form role strings with the map form.
  3. Remove null/empty entries from the section list.
  4. Fix indentation so `- name:` is at the entry level, not nested deeper.

Example fix

# before
roles:
  - geerlingguy.docker
# after
roles:
  - name: geerlingguy.docker
    version: 6.1.0
Defensive patterns

Strategy: validation

Validate before calling

fn validate_dep_entries(input: &str) -> Result<(), String> {
    let doc: serde_yaml::Value = serde_yaml::from_str(input).map_err(|e| e.to_string())?;
    for section in ["roles", "collections"] {
        if let Some(items) = doc.get(section).and_then(|s| s.as_sequence()) {
            for (i, e) in items.iter().enumerate() {
                if e.as_mapping().is_none() {
                    return Err(format!("{section}[{i}] must be a mapping with a name field"));
                }
            }
        }
    }
    Ok(())
}

Type guard

fn is_named_entry(v: &serde_yaml::Value) -> bool {
    v.as_mapping().map(|m| m.contains_key("name")).unwrap_or(false)
}

Try / catch

match pin_versions(input, &roles, &collections) {
    Err(e) if e.to_string().contains("dependency element should be a map") => {
        eprintln!("Each entry must be a map: - name: <dep> (short-form strings rejected)\n{e}");
    }
    other => other,
}

Prevention

When it happens

Trigger: A requirements file like `roles: [geerlingguy.docker]` (bare strings in the list) or `collections: - ~`; entries written as `- name: x` but mis-indented so they parse as nested lists or strings.

Common situations: Short-form role references (`- geerlingguy.docker`) which ansible-galaxy accepts but this version-pinning parser does not; YAML indentation breaking `- name:` into a scalar; empty list items (`- `) in the section.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/ba8d81ef4e8d5d1e. Report an issue: GitHub.