{"record":{"id":"dcf04f996d6ef87f","repo":"rust-lang/cargo","slug":"unexpected-btype-bracket-literal-in-build-bu-dcf04f","errorCode":null,"errorMessage":"unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}`","messagePattern":"unexpected (.+?) bracket `(.+?)` in build\\.build-dir path `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/workspace/workspace.rs","lineNumber":376,"sourceCode":"            let replacements: [(&str, &str); 0] = [];\n            let path = lockfile_path\n                    .resolve_templated_path(self.gctx(), replacements)\n                    .map_err(|e| match e {\n                        context::ResolveTemplateError::UnexpectedVariable {\n                            variable,\n                            raw_template,\n                        } => {\n                            anyhow!(\n                                \"unexpected variable `{variable}` in resolver.lockfile-path `{raw_template}`\"\n                            )\n                        }\n                        context::ResolveTemplateError::UnexpectedBracket { bracket_type, raw_template } => {\n                            let (btype, literal) = match bracket_type {\n                                context::BracketType::Opening => (\"opening\", \"{\"),\n                                context::BracketType::Closing => (\"closing\", \"}\"),\n                            };\n\n                            anyhow!(\n                                \"unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}`\"\n                            )\n                        }\n                    })?;\n            if !path.ends_with(LOCKFILE_NAME) {\n                bail!(\"the `resolver.lockfile-path` must be a path to a {LOCKFILE_NAME} file\");\n            }\n            if path.is_dir() {\n                bail!(\n                    \"`resolver.lockfile-path` `{}` is a directory but expected a file\",\n                    path.display()\n                );\n            }\n            self.requested_lockfile_path = Some(path);\n        }\n\n        Ok(())\n    }","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/rust-lang/cargo/blob/98a09e7e7d62850f14e5b6132101fc1edd19a16f/src/workspace/workspace.rs#L358-L394","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\n[resolver]\nlockfile-path = \"./build/{Cargo.lock\"\n\n# after\n[resolver]\nlockfile-path = \"./build/Cargo.lock\"","handlingStrategy":"validation","validationCode":"fn balanced_braces(s: &str) -> bool {\n    // reject any stray { or } in a path meant as a literal\n    !s.contains('{') && !s.contains('}')\n}\nlet lp: String = /* resolver.lockfile-path */;\nassert!(balanced_braces(&lp));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["config","lockfile","template","resolver","cargo"],"backgroundTag":null,"analyzedSha":"98a09e7e7d62850f14e5b6132101fc1edd19a16f","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}