{"record":{"id":"87d729603d997968","repo":"rust-lang/cargo","slug":"unexpected-variable-variable-in-resolver-lockf","errorCode":null,"errorMessage":"unexpected variable `{variable}` in resolver.lockfile-path `{raw_template}`","messagePattern":"unexpected variable `(.+?)` in resolver\\.lockfile-path `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/workspace/workspace.rs","lineNumber":366,"sourceCode":"                .feature_unification\n                .unwrap_or(FeatureUnification::Selected);\n        } else if config.feature_unification.is_some() {\n            self.gctx()\n                .shell()\n                .warn(\"ignoring `resolver.feature-unification` without `-Zfeature-unification`\")?;\n        };\n\n        if let Some(lockfile_path) = config.lockfile_path {\n            // Reserve the ability to add templates in the future.\n            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() {","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/rust-lang/cargo/blob/98a09e7e7d62850f14e5b6132101fc1edd19a16f/src/workspace/workspace.rs#L348-L384","documentation":"Cargo resolves `resolver.lockfile-path` (from config) as a templated path via `resolve_templated_path`. The replacements map is currently empty (`[(&str, &str); 0] = []`), so no variables are supported. If the template contains a `{variable}` token that is not in the (empty) replacement map, `ResolveTemplateError::UnexpectedVariable` is raised and wrapped into this anyhow error naming both the unknown variable and the raw template string.","triggerScenarios":"Setting `resolver.lockfile-path` to a string containing a brace-delimited token such as `{workspace}` or `{target}` in `.cargo/config.toml`, then triggering workspace lockfile path resolution. Because the replacements array is empty, every brace-token is unexpected.","commonSituations":"Assuming lockfile-path supports the same template variables as `build.build-dir`; copying templating syntax from docs/examples that target a different Cargo feature; using `${...}`-style or `{...}`-style placeholders expecting expansion.","solutions":["Use a literal, fully-specified file path for `resolver.lockfile-path` ending in `Cargo.lock` (the code later requires `path.ends_with(LOCKFILE_NAME)`).","Remove any `{...}` template tokens from the lockfile-path value, since no variables are currently substituted.","If you need path relativization across workspace roots, compute the absolute path externally and set the literal result."],"exampleFix":"# before\n[resolver]\nlockfile-path = \"{workspace}/Cargo.lock\"\n\n# after\n[resolver]\nlockfile-path = \"./Cargo.lock\"","handlingStrategy":"validation","validationCode":"use regex::Regex;\nfn has_brace_token(s: &str) -> bool {\n    Regex::new(r\"\\{[^}]*}\").unwrap().is_match(s)\n}\nlet lp: String = /* resolver.lockfile-path */;\nassert!(!has_brace_token(&lp), \"lockfile-path supports no variables\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat `resolver.lockfile-path` as a literal path; never insert `{...}` tokens.","Ensure the value ends with `Cargo.lock`.","Lint config files for brace tokens in keys known to accept no templates."],"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"}