{"record":{"id":"97b9e78ff5161d33","repo":"windmill-labs/windmill","slug":"expected-target-field-target-directory-for-clon","errorCode":null,"errorMessage":"Expected `target` field (target directory for cloning the repo)","messagePattern":"Expected `target` field \\(target directory for cloning the repo\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-yaml/src/lib.rs","lineNumber":683,"sourceCode":"    return None;\n}\n\nfn parse_git_repo(r: &Yaml) -> anyhow::Result<GitRepo> {\n    let Yaml::Hash(repo) = r else {\n        return Err(anyhow!(\"Should be a Map\"));\n    };\n\n    let url = repo\n        .get(&Yaml::String(\"url\".to_string()))\n        .and_then(|v| v.as_str())\n        .map(|s| s.to_string())\n        .ok_or(anyhow!(\"Expected `url` field\"))?;\n\n    let target_path = repo\n        .get(&Yaml::String(\"target\".to_string()))\n        .and_then(|v| v.as_str())\n        .map(|s| s.to_string())\n        .ok_or(anyhow!(\n            \"Expected `target` field (target directory for cloning the repo)\"\n        ))?;\n\n    let branch = repo\n        .get(&Yaml::String(\"branch\".to_string()))\n        .and_then(|v| v.as_str())\n        .map(|s| s.to_string());\n\n    let commit = repo\n        .get(&Yaml::String(\"commit\".to_string()))\n        .and_then(|v| v.as_str())\n        .map(|s| s.to_string());\n\n    Ok(GitRepo { url, commit, branch, target_path })\n}\n\nfn parse_ansible_options(opts: &Vec<Yaml>) -> AnsiblePlaybookOptions {\n    let mut ret = AnsiblePlaybookOptions {","sourceCodeStart":665,"sourceCodeEnd":701,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-yaml/src/lib.rs#L665-L701","documentation":"parse_git_repo throws this when a repo map in `git_repos` has no string `target` key. The target is the relative directory where the repo will be cloned so the ansible playbook can read it; the parser requires it and the message explains its purpose. Missing key or a non-string value both trigger it.","triggerScenarios":"A git_repos entry map provides `url` but no `target`, or `target`'s value is not a YAML string (integer, boolean, null, nested map).","commonSituations":"Assuming the repo clones into the working dir without a target; typo (`destination:`, `path:`); target value written as a number; forgetting the field when copy-editing an existing entry.","solutions":["Add a `target` key with a relative directory path string to each repo entry","Ensure the value is a string, e.g. `target: repo`","Fix key typos so the key is exactly `target`","Use a distinct target per repo to avoid clone collisions"],"exampleFix":"# before\ngit_repos:\n  - url: https://github.com/org/repo.git\n\n# after\ngit_repos:\n  - url: https://github.com/org/repo.git\n    target: repo","handlingStrategy":"validation","validationCode":"fn require_target(repo: &serde_yaml::Mapping) -> Result<&str, String> {\n    repo.get(serde_yaml::Value::String(\"target\".into()))\n        .and_then(|v| v.as_str())\n        .ok_or_else(|| \"repo entry requires a string `target` field (clone directory)\".to_string())\n}","typeGuard":"fn has_string_field(v: &Yaml, key: &str) -> bool {\n    matches!(v, Yaml::Hash(m) if matches!(m.get(&Yaml::String(key.into())), Some(Yaml::String(_))))\n}","tryCatchPattern":null,"preventionTips":["Always set `target` for each repo, even if cloning to a simple name","Use a relative path and a distinct directory per repo","Check the key is exactly `target`, not path/destination"],"tags":["yaml","ansible","git","parser"],"backgroundTag":"missing-required-argument","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}