{"record":{"id":"f9e6d0e9a4c88d29","repo":"astrid-runtime/astrid","slug":"required-variable-var-name-has-no-value-no","errorCode":null,"errorMessage":"required variable '{var_name}' has no value (no --var {var_name}=…, no {env_key}, no default)","messagePattern":"required variable '(.+?)' has no value \\(no --var (.+?)=…, no (.+?), no default\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/init.rs","lineNumber":543,"sourceCode":"    variables: &HashMap<String, super::distro::manifest::VariableDef>,\n    needed_vars: &std::collections::HashSet<String>,\n    cli_vars: &HashMap<String, String>,\n    env_lookup: impl Fn(&str) -> Option<String>,\n) -> anyhow::Result<HashMap<String, String>> {\n    let mut vars = HashMap::new();\n    let mut sorted: Vec<&str> = needed_vars.iter().map(String::as_str).collect();\n    sorted.sort_unstable();\n\n    for var_name in sorted {\n        let env_key = format!(\"ASTRID_VAR_{}\", var_name.to_uppercase());\n        let var_def = variables.get(var_name);\n        let value = cli_vars\n            .get(var_name)\n            .cloned()\n            .or_else(|| env_lookup(&env_key))\n            .or_else(|| var_def.and_then(|d| d.default.clone()))\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"required variable '{var_name}' has no value \\\n                     (no --var {var_name}=…, no {env_key}, no default)\"\n                )\n            })?;\n\n        let is_secret = var_def.is_some_and(|d| d.secret);\n        if is_secret {\n            tracing::debug!(var = %var_name, \"resolved distro variable [secret]\");\n        } else {\n            tracing::debug!(var = %var_name, value = %value, \"resolved distro variable\");\n        }\n\n        vars.insert(var_name.to_string(), value);\n    }\n\n    Ok(vars)\n}\n","sourceCodeStart":525,"sourceCodeEnd":561,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/init.rs#L525-L561","documentation":"collect_variables_headless resolves each required template variable from three sources in order: --var CLI values, the mapped environment variable, then the variable definition's default. When all three are absent for a required variable, this error names the variable, the --var flag, the expected env key, and the missing default. It exists so headless runs fail deterministically instead of prompting.","triggerScenarios":"Running `astrid init` headless (non-TTY/CI) where a template declares a required variable with no default, and the caller supplies neither --var <name>=… nor the corresponding environment variable.","commonSituations":"CI pipelines that used to prompt interactively now failing headless; secrets not exported in the CI environment; renamed env keys; templates gaining a new required variable after an update.","solutions":["Pass the value explicitly: astrid init --var <name>=<value>","Export the expected environment variable shown in the error before running init","Provide a default for the variable in the template definition","If the variable should be optional, mark it as such in the template"],"exampleFix":"// before\nastrid init --group web\n// after\nastrid init --group web --var project_name=my-app\n// or\nexport PROJECT_NAME=my-app && astrid init --group web","handlingStrategy":"validation","validationCode":"fn required_vars_missing<'a>(\n    template: &'a Template,\n    cli: &HashMap<String, String>,\n) -> Vec<&'a str> {\n    template.variables.iter()\n        .filter(|v| v.required)\n        .filter(|v| {\n            cli.contains_key(&v.name)\n                || std::env::var_os(&v.env_key).is_some()\n                || v.default.is_some()\n        }\n        .then_some(()) .is_none())\n        .map(|v| v.name.as_str())\n        .collect()\n}","typeGuard":null,"tryCatchPattern":"match collect_variables(&template, &cli_vars) {\n    Err(e) if e.to_string().contains(\"has no value\") => {\n        eprintln!(\"{e}\\nhint: pass --var or export the env var listed above\");\n        std::process::exit(2);\n    }\n    other => other?,\n}","preventionTips":["Pass all required variables via --var in CI/headless environments","Export the documented env keys in shell profiles or CI secrets","Give every required variable a sensible default in templates when possible","Preflight-check required variables before starting long init runs"],"tags":["cli","variables","headless","missing-value","environment"],"backgroundTag":"missing-required-argument","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}