facebook/relay · critical
Unable to canonicalize file {:?}. Error: {:?}
Error message
Unable to canonicalize file {:?}. Error: {:?} What it means
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.
Source
Thrown at compiler/crates/relay-compiler/src/config.rs:492
self.sender.subscribe()
}
}
impl Default for TestFileSourceConfig {
fn default() -> Self {
Self::new()
}
}
fn normalize_path_from_config(
current_dir: PathBuf,
common_path: PathBuf,
path_from_config: PathBuf,
) -> PathBuf {
let mut src = current_dir.join(path_from_config.clone());
src = canonicalize(src.clone())
.unwrap_or_else(|err| panic!("Unable to canonicalize file {:?}. Error: {:?}", src, err));
src.strip_prefix(common_path.clone())
.unwrap_or_else(|_| {
panic!(
"Expect to be able to strip common_path from {:?} {:?}",
src,
common_path.clone(),
);
})
.to_path_buf()
}
impl From<SingleProjectConfigFile> for Config {
fn from(config: SingleProjectConfigFile) -> Self {
Self::from_struct(
"/virtual/path".into(),
ConfigFile::SingleProject(config),
false,View on GitHub (pinned to 668b1b85e0)
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.
Example fix
// relay.config.js before src: './srs', // typo // after src: './src',
Defensive patterns
Strategy: validation
Validate before calling
// before running the compiler
const src = path.resolve(configDir, cfg.src);
if (!fs.existsSync(src)) throw new Error(`relay src does not exist: ${src}`); Type guard
function pathExists(p) { try { return fs.realpathSync(p) !== undefined; } catch { return false; } } Prevention
- 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)
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Expect to be able to strip common_path from {:?} {:?}
- Unable to get current working directory.
- Expected to have access to AST and docblock sources.
- LocalPersister: Unable to read the {} file: {}
- Expected the JS type for '{}' to be defined, please update '
AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02).
Data as JSON: /api/errors/1c93928f1dae6678.
Report an issue: GitHub.