{"record":{"id":"a8d734b6f2f45836","repo":"sigoden/aichat","slug":"missing-value-for-variable","errorCode":null,"errorMessage":"Missing value for variable '{}'","messagePattern":"Missing value for variable '(.+?)'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/config/mod.rs","lineNumber":2520,"sourceCode":"}\n\nimpl Macro {\n    pub fn resolve_variables(&self, args: &[String]) -> Result<IndexMap<String, String>> {\n        let mut output = IndexMap::new();\n        for (i, variable) in self.variables.iter().enumerate() {\n            let value = if variable.rest && i == self.variables.len() - 1 {\n                if args.len() > i {\n                    Some(args[i..].join(\" \"))\n                } else {\n                    variable.default.clone()\n                }\n            } else {\n                args.get(i)\n                    .map(|v| v.to_string())\n                    .or_else(|| variable.default.clone())\n            };\n            let value =\n                value.ok_or_else(|| anyhow!(\"Missing value for variable '{}'\", variable.name))?;\n            output.insert(variable.name.clone(), value);\n        }\n        Ok(output)\n    }\n\n    pub fn usage(&self, name: &str) -> String {\n        let mut parts = vec![name.to_string()];\n        for (i, variable) in self.variables.iter().enumerate() {\n            let part = match (\n                variable.rest && i == self.variables.len() - 1,\n                variable.default.is_some(),\n            ) {\n                (true, true) => format!(\"[{}]...\", variable.name),\n                (true, false) => format!(\"<{}>...\", variable.name),\n                (false, true) => format!(\"[{}]\", variable.name),\n                (false, false) => format!(\"<{}>\", variable.name),\n            };\n            parts.push(part);","sourceCodeStart":2502,"sourceCodeEnd":2538,"githubUrl":"https://github.com/sigoden/aichat/blob/82976d349ad97ac9aae0655ad631dace5e2a6385/src/config/mod.rs#L2502-L2538","documentation":"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.","triggerScenarios":"Calling the variable-resolution routine when args.get(i) returns None (fewer positional args than variables) and variable.default is None.","commonSituations":"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.","solutions":["Supply the missing positional argument in the correct order","Define a default for the variable in its declaration","Check the variable order/names in the definition to confirm which one is missing"],"exampleFix":"// before: variable declared without default\nVariable { name: \"env\", default: None }\n// after\nVariable { name: \"env\", default: Some(\"production\".into()) }","handlingStrategy":"validation","validationCode":"fn has_value(v: &Variable, args: &[String], i: usize) -> bool {\n    args.get(i).is_some() || v.default.is_some()\n}","typeGuard":"fn resolves(v: &Variable, args: &[String], i: usize) -> Option<String> {\n    args.get(i).cloned().or_else(|| v.default.clone())\n}","tryCatchPattern":"match resolve_variables(&variables, &args) {\n    Ok(map) => use(map),\n    Err(e) if e.to_string().contains(\"Missing value for variable\") => {\n        eprintln!(\"Usage: {}\", usage_hint); }\n    Err(e) => return Err(e),\n}","preventionTips":["Always provide a default for optional variables","Count arguments against declared variables before invoking","Validate CLI input length before calling the resolver"],"tags":["cli","config","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"82976d349ad97ac9aae0655ad631dace5e2a6385","analyzedAt":"2026-09-09T18:33:06.139Z","contentChangedAt":"2026-09-09T18:33:06.139Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}