{"record":{"id":"1c93928f1dae6678","repo":"facebook/relay","slug":"unable-to-canonicalize-file-error","errorCode":null,"errorMessage":"Unable to canonicalize file {:?}. Error: {:?}","messagePattern":"Unable to canonicalize file (.+?)\\. Error: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/crates/relay-compiler/src/config.rs","lineNumber":492,"sourceCode":"        self.sender.subscribe()\n    }\n}\n\nimpl 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,","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-compiler/src/config.rs#L474-L510","documentation":"normalize_path_from_config joins the config-relative path with the current directory and calls canonicalize; if the path does not exist or cannot be resolved (symlink loops, permissions), it panics with this message. The compiler requires every source path in relay.config to resolve to a real file/directory on disk.","triggerScenarios":"Calling create_multi_project_config / ConfigFileProject with a src or path_from_config entry in the config that does not exist relative to the config's directory, or a path whose canonicalization fails (broken symlink, permission denied).","commonSituations":"Typo'd or moved src directory in relay.config.js; running the compiler from a different working directory than expected; broken symlink; running in a container where the source dir was not mounted.","solutions":["Verify the path in your relay config exists relative to the config file location (ls it).","Run the compiler from the project root where the config's relative paths are valid.","Fix or remove broken symlinks and check read permissions on the path.","If generated/moved dirs are the issue, update the config's path entries to the new location."],"exampleFix":"// relay.config.js before\nsrc: './srs', // typo\n// after\nsrc: './src',","handlingStrategy":"validation","validationCode":"// before running the compiler\nconst src = path.resolve(configDir, cfg.src);\nif (!fs.existsSync(src)) throw new Error(`relay src does not exist: ${src}`);","typeGuard":"function pathExists(p) { try { return fs.realpathSync(p) !== undefined; } catch { return false; } }","tryCatchPattern":null,"preventionTips":["Keep relay config paths relative to the config file and verify them in CI","Avoid symlinks pointing outside the project root","Run the compiler from a stable working directory (package script)"],"tags":["config","filesystem","path","panic"],"backgroundTag":"file-not-found","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}