{"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":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/workspace/workspace.rs","lineNumber":380,"sourceCode":"            if config.incompatible_publish_age.is_some() {\n                self.gctx().shell().warn(\n                    \"ignoring `resolver.incompatible-publish-age` without `-Zmin-publish-age`\",\n                )?;\n            }\n            warn_unused_min_publish_age(self.gctx())?;\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":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/workspace/workspace.rs#L362-L398","documentation":"Thrown while resolving `resolver.lockfile-path` in `Workspace::validate` (src/workspace/workspace.rs:373). Cargo calls `resolve_templated_path` with an empty replacements table (`let replacements: [(&str, &str); 0] = [];` at line 372), so ANY `{variable}` form in the path is rejected as `UnexpectedVariable`. The error echoes the offending variable name and the raw template.","triggerScenarios":"Setting `resolver.lockfile-path = \"{workspace_root}/Cargo.lock\"` or any value containing a `{...}` token in `.cargo/config.toml` or the workspace manifest — because no template variables are currently supported for this field.","commonSituations":"Assuming lockfile-path supports the same templating as other cargo config fields; copy-pasting a templated path from documentation for a different field; leftover `{}` placeholders from migration tooling.","solutions":["Remove all `{...}` template syntax from `resolver.lockfile-path` and use a concrete relative or absolute path.","If you need workspace-root-relative behavior, compute the path out-of-band (env var, build script) since cargo does not expand variables here.","Verify the value comes from the right config layer if you did not set it explicitly."],"exampleFix":"# before\n[resolver]\nlockfile-path = \"{workspace_root}/Cargo.lock\"\n# after\n[resolver]\nlockfile-path = \"Cargo.lock\"","handlingStrategy":"validation","validationCode":"fn has_template_vars(s: &str) -> bool { s.contains('{') || s.contains('}') }\n// reject resolver.lockfile-path values with any template syntax\nassert!(!has_template_vars(&lockfile_path));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not use {variable} syntax in resolver.lockfile-path — no variables are supported.","Use a concrete path; compute workspace-relative paths outside cargo."],"tags":["cargo","config","lockfile","resolver","template"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}