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

unexpected bracket ` ` in build.build-dir path

Error message

unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}`

What it means

Thrown when resolving the build.build-dir template path and encountering a curly brace that is not part of a valid variable — either an opening brace { without a matching closing brace }, or a closing brace } without a preceding opening brace.

Solutions

  1. Ensure every opening brace { has a matching closing brace }
  2. If the path legitimately needs a literal brace character, this is not currently supported — use a different path
  3. Remove the template syntax entirely and use a plain path if template variables are not needed

Example fix

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

# after
[build]
build-dir = "{user}/target"
Defensive patterns

Strategy: validation

Validate before calling

// Check for balanced braces in template strings
fn validate_braces(s: &str) -> Result<(), String> {
    let mut depth = 0;
    for (i, c) in s.chars().enumerate() {
        match c {
            '{' => depth += 1,
            '}' => { depth -= 1; if depth < 0 { return Err(format!("unmatched closing brace at position {i}")); } }
            _ => {}
        }
    }
    if depth != 0 { return Err("unmatched opening brace".into()); }
    Ok(())
}

Prevention

When it happens

Trigger: Setting build.build-dir to a path with mismatched braces, e.g. `{user/target`, `user}/target`, or a stray brace in a directory name.

Common situations: Typo in the template syntax. Copy-pasting a path that accidentally includes a brace character. Directory name that legitimately contains a brace character but is not intended as a template.

Related errors


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

Appendix: source

Thrown at src/context/mod.rs:809

                    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!(
                "the build directory is set to an empty string in {}",
                val.value().definition
            )
        }

        Ok(Filesystem::new(path))
    }

    /// Get a configuration value by key.
    ///

View on GitHub (pinned to 98a09e7e7d)