rust-lang/cargo · error · anyhow::Error

unexpected variable ` ` in build.build-dir path

Error message

unexpected variable `{variable}` in build.build-dir path `{raw_template}`{suggestion}

What it means

Thrown when resolving the build.build-dir configuration key and the template path contains a variable in curly braces that is not one of the supported template variables. Cargo enumerates available variables and provides them in the help text of the error message.

Solutions

  1. Read the help text in the error message which lists all available template variables
  2. Use only supported variables such as `{cwd}`, `{user}`, `{project}`, etc. as listed in the error output
  3. If you do not need template substitution, use a plain absolute or relative path without curly braces

Example fix

# before (config.toml)
[build]
build-dir = "{usr}/cargo-target"

# after — use a valid variable or literal path
[build]
build-dir = "{user}/cargo-target"
Defensive patterns

Strategy: validation

Validate before calling

// Validate build-dir template variables before use
const VALID_VARS: &[&str] = &["cwd", "user", "project"];
fn validate_build_dir_template(template: &str) -> Result<(), String> {
    let re = regex::Regex::new(r"\{([a-zA-Z_][a-zA-Z0-9_]*)\}").unwrap();
    for cap in re.captures_iter(template) {
        let var = &cap[1];
        if !VALID_VARS.contains(&var) {
            return Err(format!("unknown template variable: {{{var}}}"));
        }
    }
    Ok(())
}

Prevention

When it happens

Trigger: Setting build.build-dir in config.toml (or CARGO_BUILD_BUILD_DIR env var) to a path containing an unsupported template variable, e.g. `{user}/target` when `{user}` is not a valid variable.

Common situations: Typo in a template variable name. Using a variable from documentation that was renamed or removed. Assuming a variable exists when it does not.

Related errors


AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11). Data as JSON: /api/errors/d5276b83965b4d66. Report an issue: GitHub.

Appendix: source

Thrown at src/context/mod.rs:799

        let template_variables = replacements
            .iter()
            .map(|(key, _)| key[1..key.len() - 1].to_string())
            .collect_vec();

        let path = val
            .resolve_templated_path(self, replacements)
            .map_err(|e| match e {
                path::ResolveTemplateError::UnexpectedVariable {
                    variable,
                    raw_template,
                } => {
                    let mut suggestion = closest_msg(&variable, template_variables.iter(), |key| key, "template variable");
                    if suggestion == "" {
                        let variables = template_variables.iter().map(|v| format!("`{{{v}}}`")).join(", ");
                        suggestion = format!("\n\nhelp: available template variables are {variables}");
                    }
                    anyhow!(
                            "unexpected variable `{variable}` in build.build-dir path `{raw_template}`{suggestion}"
                        )
                }
                path::ResolveTemplateError::UnexpectedBracket { bracket_type, raw_template } => {
                    let (btype, literal) = match bracket_type {
                        path::BracketType::Opening => ("opening", "{"),
                        path::BracketType::Closing => ("closing", "}"),
                    };

                    anyhow!(
                            "unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}`"
                        )
                }
            })?;

        // Check if the target directory is set to an empty string in the config.toml file.
        if val.raw_value().is_empty() {
            bail!(

View on GitHub (pinned to 98a09e7e7d)