windmill-labs/windmill · error

Files should have a `resource` or `variable` field that will

Error message

Files should have a `resource` or `variable` field that will be the contents of the local text file

What it means

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.

Source

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

                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`"));
            }
        }

        if let Some(Yaml::String(resource_path)) = f.get(&Yaml::String("resource".to_string())) {
            return Ok(FileResource {
                resource_path: ResourceOrVariablePath::Resource(resource_path.clone()),
                target_path,
                mode,
            });
        }
        if let Some(Yaml::String(resource_path)) = f.get(&Yaml::String("variable".to_string())) {
            return Ok(FileResource {
                resource_path: ResourceOrVariablePath::Variable(resource_path.clone()),
                target_path,
                mode,
            });
        }
        return Err(anyhow!(
            "Files should have a `resource` or `variable` field that will be the contents of the local text file"
        ));
    }
    return Err(anyhow!("Invalid file resource: Should be a dictionary."));
}

fn yaml_to_json(yaml: &Yaml) -> serde_json::Value {
    match yaml {
        Yaml::Array(arr) => {
            let json_array: Vec<serde_json::Value> = arr.into_iter().map(yaml_to_json).collect();
            serde_json::Value::Array(json_array)
        }
        Yaml::Hash(hash) => {
            let json_object = hash
                .into_iter()
                .map(|(k, v)| {
                    let key = match k {
                        Yaml::String(s) => s.clone(),

View on GitHub (pinned to e474e8803c)

Solutions

  1. Add a `resource: <resource-path>` field pointing to the Windmill resource holding the file contents.
  2. Or add a `variable: <variable-path>` field pointing to a Windmill variable.
  3. Make sure the value is a plain quoted string, not a nested map or number.
  4. Check spelling: the keys must be exactly `resource` or `variable` (and `target` is still required).

Example fix

// before
files:
  - target: /etc/app.conf
// after
files:
  - target: /etc/app.conf
    resource: u/admin/app_config
Defensive patterns

Strategy: validation

Validate before calling

fn validate_file_entry(entry: &serde_yaml::Value) -> Result<(), String> {
    if !entry.get("target").map(|t| t.is_string()).unwrap_or(false) {
        return Err("missing string `target`".into());
    }
    let has_source = entry.get("resource").map(|v| v.is_string()).unwrap_or(false)
        || entry.get("variable").map(|v| v.is_string()).unwrap_or(false);
    if !has_source { Err("file needs `resource` or `variable` string field".into()) } else { Ok(()) }
}

Type guard

fn has_content_source(m: &serde_yaml::Mapping) -> bool {
    m.contains_key("resource") || m.contains_key("variable")
}

Try / catch

match deploy(yaml) {
    Err(e) if e.to_string().contains("`resource` or `variable`") => {
        eprintln!("Add resource: <path> or variable: <path> to each file entry\n{e}");
    }
    other => other,
}

Prevention

When it happens

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

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

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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