windmill-labs/windmill · error

Error updating role versions: {e}

Error message

Error updating role versions: {e}

What it means

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.

Source

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

    }

    Ok(logs)
}

pub fn add_versions_to_requirements_yaml(
    input: &str,
    role_versions: &HashMap<String, String>,
    collection_versions: &HashMap<String, String>,
) -> anyhow::Result<(String, String)> {
    let mut docs =
        YamlLoader::load_from_str(input).map_err(|e| anyhow!("YAML parse error: {}", e))?;
    let doc = &mut docs[0];

    let mut logs = String::new();

    logs.push_str(
        &update_versions("roles", doc, role_versions)
            .map_err(|e| anyhow!("Error updating role versions: {e}"))?,
    );
    logs.push_str(
        &update_versions("collections", doc, collection_versions)
            .map_err(|e| anyhow!("Error updating collection versions: {e}"))?,
    );

    if !logs.is_empty() {
        logs.push_str("WARNING: You might want to try adding manual versions for these, otherwise there could be breaking changes on deployed scripts\n");
    }

    let mut out_str = String::new();
    {
        let mut emitter = YamlEmitter::new(&mut out_str);
        emitter
            .dump(doc)
            .map_err(|e| anyhow!("YAML emit error: {}", e))?;
    }

View on GitHub (pinned to e474e8803c)

Solutions

  1. Read the wrapped inner message after the prefix to identify the structural problem.
  2. Ensure the document root is a map and `roles:` is a list of {name, ...} maps.
  3. Convert short-form or src-based role entries to `name:`-based maps.
  4. Validate the YAML structure before deploying.

Example fix

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

Strategy: validation

Validate before calling

fn validate_roles(input: &str) -> Result<(), String> {
    let doc: serde_yaml::Value = serde_yaml::from_str(input).map_err(|e| e.to_string())?;
    let root = doc.as_mapping().ok_or("root must be a map")?;
    if let Some(items) = root.get("roles").and_then(|s| s.as_sequence()) {
        for e in items {
            if e.get("name").map(|n| n.is_string()) != Some(true) {
                return Err("each role needs a string name".into());
            }
        }
    }
    Ok(())
}

Type guard

fn roles_are_pinnable(v: &serde_yaml::Value) -> bool {
    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)
}

Try / catch

match pin_versions(input, &roles, &collections) {
    Err(e) if e.to_string().contains("Error updating role versions") => {
        eprintln!("Roles section invalid (see inner message): entries need name fields\n{e}");
    }
    other => other,
}

Prevention

When it happens

Trigger: 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`.

Common situations: 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.

Related errors


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