rust-lang/cargo · error
unexpected variable `{variable}` in build.build-dir path `{r
Error message
unexpected variable `{variable}` in build.build-dir path `{raw_template}`{suggestion} What it means
custom_build_dir (mod.rs:762-824) resolves the `build.build-dir` config value, which supports a limited set of template variables: `{workspace-root}`, `{cargo-cache-home}`, `{workspace-path-hash}`. If the template contains any other `{...}` token, resolve_templated_path returns UnexpectedVariable and Cargo bails 'unexpected variable `<var>` in build.build-dir path `<template>`<suggestion>', appending either a closest-match hint or a list of available variables.
Source
Thrown at src/context/mod.rs:810
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 0e07a15537)
Solutions
- Use only the supported variables: `{workspace-root}`, `{cargo-cache-home}`, `{workspace-path-hash}` (see the help line in the error).
- If you need a literal path with braces, avoid the `{...}` shape or escape per the docs.
- Fix typos based on the closest-match suggestion in the message.
Example fix
# before (.cargo/config.toml)
[build]
build-dir = "/cache/{name}/target" # {name} unsupported
# after
[build]
build-dir = "/cache/{workspace-path-hash}/target" Defensive patterns
Strategy: validation
Validate before calling
# Validate build-dir uses only supported template variables:
python3 - <<'EOF'
import tomllib, re, sys
try:
d = tomllib.load(open('.cargo/config.toml','rb'))
except FileNotFoundError: sys.exit(0)
bd = d.get('build',{}).get('build-dir')
if bd:
allowed = {'{workspace-root}','{cargo-cache-home}','{workspace-path-hash}'}
found = set(re.findall(r'\{[^}]*\}', bd))
bad = found - allowed
assert not bad, f'unsupported build-dir variables: {bad}'
EOF Prevention
- Restrict build-dir template variables to the documented set.
- Lint .cargo/config.toml in CI for unsupported variables.
- Read the suggestion line in the error; it lists valid variables.
When it happens
Trigger: Setting `build.build-dir = "/some/{name}/target"` in config.toml where `{name}` is not one of the supported template variables. Also a literal `{` intended as a path char interpreted as a variable start.
Common situations: Trying to template build-dir on the package name or a custom variable; typo in a supported variable name like `{workspace-root}` misspelled.
Related errors
- unexpected {btype} bracket `{literal}` in build.build-dir pa
- unexpected variable `{variable}` in resolver.lockfile-path `
- unexpected {btype} bracket `{literal}` in build.build-dir pa
- no executable for `{}` found in PATH
- subcommand is required, add a subcommand to the command alia
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/d5276b83965b4d66.json.
Report an issue: GitHub.