sigoden/aichat · error · anyhow::Error

Missing value for variable

Error message

Missing value for variable '{}'

What it means

Thrown when resolving CLI/config variables: a variable has neither a positional argument nor a default value, so the resolved value is None. The library requires every declared variable to resolve to a string before inserting it into the output map. It uses anyhow! to attach the variable name for diagnosis.

Solutions

  1. Supply the missing positional argument in the correct order
  2. Define a default for the variable in its declaration
  3. Check the variable order/names in the definition to confirm which one is missing

Example fix

// before: variable declared without default
Variable { name: "env", default: None }
// after
Variable { name: "env", default: Some("production".into()) }
Defensive patterns

Strategy: validation

Validate before calling

fn has_value(v: &Variable, args: &[String], i: usize) -> bool {
    args.get(i).is_some() || v.default.is_some()
}

Type guard

fn resolves(v: &Variable, args: &[String], i: usize) -> Option<String> {
    args.get(i).cloned().or_else(|| v.default.clone())
}

Try / catch

match resolve_variables(&variables, &args) {
    Ok(map) => use(map),
    Err(e) if e.to_string().contains("Missing value for variable") => {
        eprintln!("Usage: {}", usage_hint); }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling the variable-resolution routine when args.get(i) returns None (fewer positional args than variables) and variable.default is None.

Common situations: Invoking a command/template that declares a variable but the user supplies fewer arguments than expected; forgetting to define a default for an optional-looking variable; scripts calling the binary programmatically with a truncated argument list.

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 sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/a8d734b6f2f45836. Report an issue: GitHub.

Appendix: source

Thrown at src/config/mod.rs:2520

}

impl Macro {
    pub fn resolve_variables(&self, args: &[String]) -> Result<IndexMap<String, String>> {
        let mut output = IndexMap::new();
        for (i, variable) in self.variables.iter().enumerate() {
            let value = if variable.rest && i == self.variables.len() - 1 {
                if args.len() > i {
                    Some(args[i..].join(" "))
                } else {
                    variable.default.clone()
                }
            } else {
                args.get(i)
                    .map(|v| v.to_string())
                    .or_else(|| variable.default.clone())
            };
            let value =
                value.ok_or_else(|| anyhow!("Missing value for variable '{}'", variable.name))?;
            output.insert(variable.name.clone(), value);
        }
        Ok(output)
    }

    pub fn usage(&self, name: &str) -> String {
        let mut parts = vec![name.to_string()];
        for (i, variable) in self.variables.iter().enumerate() {
            let part = match (
                variable.rest && i == self.variables.len() - 1,
                variable.default.is_some(),
            ) {
                (true, true) => format!("[{}]...", variable.name),
                (true, false) => format!("<{}>...", variable.name),
                (false, true) => format!("[{}]", variable.name),
                (false, false) => format!("<{}>", variable.name),
            };
            parts.push(part);

View on GitHub (pinned to 82976d349a)