rust-lang/cargo · error
unexpected bracket ` ` in build.build-dir path
Error message
unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}` What it means
During the same `resolver.lockfile-path` templated-path resolution, if the template contains a stray opening (`{`) or closing (`}`) bracket that does not form a valid variable token, `ResolveTemplateError::UnexpectedBracket` is raised. The code maps `BracketType::Opening` to the string `"opening"` + literal `{`, and `BracketType::Closing` to `"closing"` + literal `}`, then interpolates them into the message. Note the message text references `build.build-dir` even though this branch fires during lockfile-path resolution — a likely copy-paste artifact in the source.
Solutions
- Remove stray `{` or `}` characters from the `resolver.lockfile-path` value so the template is a plain path.
- Verify the path ends with `Cargo.lock` and contains no brace tokens (none are supported).
- If you need a literal brace in a path (unusual), avoid this config key since the templater will always interpret braces.
Example fix
# before
[resolver]
lockfile-path = "./build/{Cargo.lock"
# after
[resolver]
lockfile-path = "./build/Cargo.lock" Defensive patterns
Strategy: validation
Validate before calling
fn balanced_braces(s: &str) -> bool {
// reject any stray { or } in a path meant as a literal
!s.contains('{') && !s.contains('}')
}
let lp: String = /* resolver.lockfile-path */;
assert!(balanced_braces(&lp)); Prevention
- Avoid brace characters entirely in lockfile-path values.
- Double-check Windows/shell variable syntax does not leak into Cargo config.
- Lint config values for unbalanced braces before committing.
When it happens
Trigger: Setting `resolver.lockfile-path` to a value with an unbalanced brace such as `./Cargo.lock{` or `./lock}` — a brace that the template parser treats as a bracket token rather than a literal — during `resolve_templated_path` with the empty replacements map.
Common situations: Windows path or shell-variable artifacts leaking into the config (`${HOME}`), JSON/TOML escaping mistakes producing stray braces, or hand-editing the config and leaving a dangling bracket.
Related errors
- unexpected variable ` ` in resolver.lockfile-path
- can't find library ` `, rename file to `src/lib.rs` or…
- cannot mix `proc-macro` crate type with others
- cannot specify both `metabuild` and `build`
- config.json not found
AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11).
Data as JSON: /api/errors/dcf04f996d6ef87f.
Report an issue: GitHub.
Appendix: source
Thrown at src/workspace/workspace.rs:376
let replacements: [(&str, &str); 0] = [];
let path = lockfile_path
.resolve_templated_path(self.gctx(), replacements)
.map_err(|e| match e {
context::ResolveTemplateError::UnexpectedVariable {
variable,
raw_template,
} => {
anyhow!(
"unexpected variable `{variable}` in resolver.lockfile-path `{raw_template}`"
)
}
context::ResolveTemplateError::UnexpectedBracket { bracket_type, raw_template } => {
let (btype, literal) = match bracket_type {
context::BracketType::Opening => ("opening", "{"),
context::BracketType::Closing => ("closing", "}"),
};
anyhow!(
"unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}`"
)
}
})?;
if !path.ends_with(LOCKFILE_NAME) {
bail!("the `resolver.lockfile-path` must be a path to a {LOCKFILE_NAME} file");
}
if path.is_dir() {
bail!(
"`resolver.lockfile-path` `{}` is a directory but expected a file",
path.display()
);
}
self.requested_lockfile_path = Some(path);
}
Ok(())
}View on GitHub (pinned to 98a09e7e7d)