windmill-labs/windmill · error

git_ssh_identity expects an array of windmill variables (or

Error message

git_ssh_identity expects an array of windmill variables (or secrets) containing ssh IDs

What it means

extract_ssh_identity throws this when the `git_ssh_identity` field in an ansible playbook requirement YAML is not a YAML array. The field is expected to be a list of strings, each naming a Windmill variable (or secret) that holds an SSH identity file path used for git authentication. A scalar or map value fails the `Yaml::Array` match and aborts parsing.

Source

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

                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)),
                _ => (),
            }
        }
    }

    let mut out_str = String::new();
    let mut emitter = YamlEmitter::new(&mut out_str);

    for i in 1..docs.len() {
        emitter.dump(&docs[i])?;
    }
    Ok((logs, Some(ret), out_str))
}

fn extract_ssh_identity(value: &Yaml, ret: &mut Vec<String>) -> anyhow::Result<()> {
    let Yaml::Array(indentities) = value else {
        return Err(anyhow!(
            "git_ssh_identity expects an array of windmill variables (or secrets) containing ssh IDs"
        ));
    };

    for r in indentities {
        let Yaml::String(file_name) = r else {
            return Err(anyhow!(
                "Git ssh identity file must be a string path to a Windmill variable/secret"
            ));
        };

        ret.push(file_name.clone());
    }
    Ok(())
}

fn extract_delegate_to_git_repo_details(value: &Yaml) -> Option<DelegateToGitRepoDetails> {
    if let Yaml::Hash(v) = value {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Wrap the identity reference(s) in a YAML list, even for a single entry
  2. Each list item must be a string path to a Windmill variable/secret (e.g. `- u$username_var`)
  3. Verify indentation places the string(s) as list items under git_ssh_identity
  4. If you intended one file path like vault_password, remember this field is always an array

Example fix

# before
git_ssh_identity: u$my_ssh_key_var

# after
git_ssh_identity:
  - u$my_ssh_key_var
Defensive patterns

Strategy: validation

Validate before calling

fn validate_git_ssh_identity(value: &serde_yaml::Value) -> Result<(), String> {
    match value.get("git_ssh_identity") {
        None => Ok(()),
        Some(v) => match v {
            serde_yaml::Value::Sequence(items) if items.iter().all(|i| i.is_string()) => Ok(()),
            other => Err(format!("git_ssh_identity must be a list of strings, got: {:?}", other)),
        },
    }
}

Type guard

fn is_string_array(v: &Yaml) -> bool {
    matches!(v, Yaml::Array(items) if items.iter().all(|i| matches!(i, Yaml::String(_))))
}

Prevention

When it happens

Trigger: parse_ansible_reqs or parse_delegate_to_git_repo calls extract_ssh_identity with a `git_ssh_identity` value that is a single string, map, or null rather than a sequence of strings.

Common situations: Specifying a single identity without list syntax (`git_ssh_identity: u$username_var` instead of a `- u$username_var` item); confusing this field with `vault_password` which does take a bare string; YAML anchors resolving to a scalar.

Related errors


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