{"record":{"id":"ecdafba77751450d","repo":"jdx/mise","slug":"relative-repo-path-path-raw-must-name-a-direct","errorCode":null,"errorMessage":"relative repo path `{path_raw}` must name a directory inside the project root","messagePattern":"relative repo path `(.+?)` must name a directory inside the project root","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/repos.rs","lineNumber":108,"sourceCode":"                bail!(\n                    \"relative repo paths are only allowed in a project config; use an absolute path or a `~/` path\"\n                );\n            };\n            if path.components().any(|component| {\n                matches!(\n                    component,\n                    Component::ParentDir | Component::RootDir | Component::Prefix(_)\n                )\n            }) {\n                bail!(\n                    \"relative repo path `{path_raw}` must stay within the project root (no `..` or absolute segments)\"\n                );\n            }\n            if !path\n                .components()\n                .any(|component| matches!(component, Component::Normal(_)))\n            {\n                bail!(\n                    \"relative repo path `{path_raw}` must name a directory inside the project root\"\n                );\n            }\n            // Join only the Normal segments so `./foobar` resolves to\n            // `<root>/foobar` rather than `<root>/./foobar` — a `.` component\n            // survives `Path::join` and leaks into every displayed path.\n            let mut resolved = root.to_path_buf();\n            for component in path.components() {\n                if let Component::Normal(segment) = component {\n                    resolved.push(segment);\n                }\n            }\n            resolved\n        };\n        let Some(url) = config.url.map(|s| s.trim().to_string()) else {\n            bail!(\"must set `url`\");\n        };\n        if url.is_empty() {","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/repos.rs#L90-L126","documentation":"After rejecting traversal components, from_toml requires a relative repo key to contain at least one Normal path component. A path that is only `.`/`./` (or otherwise empty after expansion) would resolve to the project root itself, which is not a valid checkout directory. This ensures every relative repo entry names a real subdirectory inside the project.","triggerScenarios":"Setting a bootstrap repo key to `\".\"`, `\"./\"`, or `\"\"`-equivalent relative forms in a project config so that replace_path yields no Normal components.","commonSituations":"Trying to bootstrap the project root itself as a repo; accidentally leaving a placeholder `.` key when editing mise.toml; copy/paste that dropped the subdirectory part of the path.","solutions":["Replace the key with the intended subdirectory, e.g. `\"dotfiles\"` or `\"./vendor/lib\"`","If the checkout should be the project root, use an absolute path or `~/` path key instead","Remove the entry if it was a placeholder"],"exampleFix":"// before\n[bootstrap.repos]\n\".\" = { url = \"https://github.com/jdx/dotfiles.git\" }\n// after\n[bootstrap.repos]\n\"dotfiles\" = { url = \"https://github.com/jdx/dotfiles.git\" }","handlingStrategy":"validation","validationCode":"fn names_a_directory(p: &str) -> bool {\n    std::path::Path::new(p).components().any(|c| matches!(c, std::path::Component::Normal(_)))\n}\n// assert!(names_a_directory(\"dotfiles\"))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always key a repo by its checkout subdirectory, never `.` or the project root","Review repo keys after copy/paste; placeholders like `.` indicate unfinished config","Keep one repo per subdirectory entry in `[bootstrap.repos]`"],"tags":["config","path","git","bootstrap"],"backgroundTag":"invalid-argument-value","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}