{"record":{"id":"6ea0876a80485c99","repo":"facebook/relay","slug":"expect-to-be-able-to-strip-common-path-from","errorCode":null,"errorMessage":"Expect to be able to strip common_path from {:?} {:?}","messagePattern":"Expect to be able to strip common_path from (.+?) (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/crates/relay-compiler/src/config.rs","lineNumber":496,"sourceCode":"impl Default for TestFileSourceConfig {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nfn normalize_path_from_config(\n    current_dir: PathBuf,\n    common_path: PathBuf,\n    path_from_config: PathBuf,\n) -> PathBuf {\n    let mut src = current_dir.join(path_from_config.clone());\n\n    src = canonicalize(src.clone())\n        .unwrap_or_else(|err| panic!(\"Unable to canonicalize file {:?}. Error: {:?}\", src, err));\n\n    src.strip_prefix(common_path.clone())\n        .unwrap_or_else(|_| {\n            panic!(\n                \"Expect to be able to strip common_path from {:?} {:?}\",\n                src,\n                common_path.clone(),\n            );\n        })\n        .to_path_buf()\n}\n\nimpl From<SingleProjectConfigFile> for Config {\n    fn from(config: SingleProjectConfigFile) -> Self {\n        Self::from_struct(\n            \"/virtual/path\".into(),\n            ConfigFile::SingleProject(config),\n            false,\n        )\n        .unwrap()\n    }\n}","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-compiler/src/config.rs#L478-L514","documentation":"After canonicalizing the source path, normalize_path_from_config strips the shared common_path prefix so relative project paths can be computed. If the canonicalized src is not under common_path, stripping fails and the compiler panics, since its path model assumes all project sources live under the common root.","triggerScenarios":"create_multi_project_config with a project's src that canonicalizes to a location outside common_path — e.g. a symlink pointing outside the root, a src defined as an absolute path elsewhere, or overlapping project roots that don't share the computed prefix.","commonSituations":"Symlinked src directories resolving outside the repo; multi-project configs where one project's directory sits outside the common root; canonicalization turning ./a/../b into a path that escapes common_path.","solutions":["Ensure each project's src is physically (post-symlink-resolution) inside the common root directory.","Check symlink targets with realpath and point them inside the repo.","Restructure multi-project config so all project directories share a common ancestor that the compiler computes as common_path.","Avoid absolute paths pointing outside the project tree in the config."],"exampleFix":"// before\nsrc: path.resolve('/external/libs/ui'), // outside common root\n// after\nsrc: './packages/ui',","handlingStrategy":"validation","validationCode":"const canon = fs.realpathSync(path.resolve(cfg.src));\nconst common = fs.realpathSync(commonRoot);\nif (!canon.startsWith(common + path.sep)) throw new Error(`src ${canon} is outside common root ${common}`);","typeGuard":"function isUnderRoot(child, root) { const c = path.resolve(child), r = path.resolve(root); return c === r || c.startsWith(r + path.sep); }","tryCatchPattern":null,"preventionTips":["Resolve symlinks (realpath) before asserting project layout","Keep all multi-project sources under one common ancestor","Avoid absolute paths outside the repo in relay configs"],"tags":["config","filesystem","path","panic"],"backgroundTag":"path-prefix-mismatch","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}