{"record":{"id":"74e85dbd95e9e8e3","repo":"windmill-labs/windmill","slug":"files-should-have-a-resource-or-variable-field","errorCode":null,"errorMessage":"Files should have a `resource` or `variable` field that will be the contents of the local text file","messagePattern":"Files should have a `resource` or `variable` field that will be the contents of the local text file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-yaml/src/lib.rs","lineNumber":839,"sourceCode":"                return Err(anyhow!(\"The provided value for `mode` is too big. Make sure that you are using the octal prefix (0o), e.g. `mode: 0o644`\"));\n            }\n        }\n\n        if let Some(Yaml::String(resource_path)) = f.get(&Yaml::String(\"resource\".to_string())) {\n            return Ok(FileResource {\n                resource_path: ResourceOrVariablePath::Resource(resource_path.clone()),\n                target_path,\n                mode,\n            });\n        }\n        if let Some(Yaml::String(resource_path)) = f.get(&Yaml::String(\"variable\".to_string())) {\n            return Ok(FileResource {\n                resource_path: ResourceOrVariablePath::Variable(resource_path.clone()),\n                target_path,\n                mode,\n            });\n        }\n        return Err(anyhow!(\n            \"Files should have a `resource` or `variable` field that will be the contents of the local text file\"\n        ));\n    }\n    return Err(anyhow!(\"Invalid file resource: Should be a dictionary.\"));\n}\n\nfn yaml_to_json(yaml: &Yaml) -> serde_json::Value {\n    match yaml {\n        Yaml::Array(arr) => {\n            let json_array: Vec<serde_json::Value> = arr.into_iter().map(yaml_to_json).collect();\n            serde_json::Value::Array(json_array)\n        }\n        Yaml::Hash(hash) => {\n            let json_object = hash\n                .into_iter()\n                .map(|(k, v)| {\n                    let key = match k {\n                        Yaml::String(s) => s.clone(),","sourceCodeStart":821,"sourceCodeEnd":857,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-yaml/src/lib.rs#L821-L857","documentation":"Every file resource parsed by parse_file_resource must carry its content source: a `resource` field (path/path-variable to a Windmill resource) or a `variable` field (path/path-variable to a Windmill variable). This error is thrown when the entry is a valid dictionary with a `target` but neither key is present, so the parser cannot know what contents to write to the local file.","triggerScenarios":"Deploying YAML with a files entry that only specifies `target` (and possibly `mode`), e.g. `files: [{ target: /etc/app.conf }]`. Also thrown if `resource`/`variable` exist but are not plain strings (e.g. a map or integer), since the pattern match requires Yaml::String.","commonSituations":"Hand-writing an ansible script's `files` section and forgetting the content source; renaming the field to `content` or `path`; nesting the value so YAML sees a map rather than a string; typos like `resouce` or `variables`.","solutions":["Add a `resource: <resource-path>` field pointing to the Windmill resource holding the file contents.","Or add a `variable: <variable-path>` field pointing to a Windmill variable.","Make sure the value is a plain quoted string, not a nested map or number.","Check spelling: the keys must be exactly `resource` or `variable` (and `target` is still required)."],"exampleFix":"// before\nfiles:\n  - target: /etc/app.conf\n// after\nfiles:\n  - target: /etc/app.conf\n    resource: u/admin/app_config","handlingStrategy":"validation","validationCode":"fn validate_file_entry(entry: &serde_yaml::Value) -> Result<(), String> {\n    if !entry.get(\"target\").map(|t| t.is_string()).unwrap_or(false) {\n        return Err(\"missing string `target`\".into());\n    }\n    let has_source = entry.get(\"resource\").map(|v| v.is_string()).unwrap_or(false)\n        || entry.get(\"variable\").map(|v| v.is_string()).unwrap_or(false);\n    if !has_source { Err(\"file needs `resource` or `variable` string field\".into()) } else { Ok(()) }\n}","typeGuard":"fn has_content_source(m: &serde_yaml::Mapping) -> bool {\n    m.contains_key(\"resource\") || m.contains_key(\"variable\")\n}","tryCatchPattern":"match deploy(yaml) {\n    Err(e) if e.to_string().contains(\"`resource` or `variable`\") => {\n        eprintln!(\"Add resource: <path> or variable: <path> to each file entry\\n{e}\");\n    }\n    other => other,\n}","preventionTips":["Every file entry needs exactly one of resource:/variable: besides target:","Keys must be spelled exactly `resource` / `variable` (no `content`, `src`, `path`)","Values must be plain strings — quote paths that could be misread as numbers","Validate the full files schema with a JSON/YAML schema before deploy"],"tags":["yaml","missing-field","file-resource","ansible"],"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"}