facebook/relay · critical

Expect to be able to strip common_path from {:?} {:?}

Error message

Expect to be able to strip common_path from {:?} {:?}

What it means

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.

Source

Thrown at compiler/crates/relay-compiler/src/config.rs:496

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,
        )
        .unwrap()
    }
}

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Ensure each project's src is physically (post-symlink-resolution) inside the common root directory.
  2. Check symlink targets with realpath and point them inside the repo.
  3. Restructure multi-project config so all project directories share a common ancestor that the compiler computes as common_path.
  4. Avoid absolute paths pointing outside the project tree in the config.

Example fix

// before
src: path.resolve('/external/libs/ui'), // outside common root
// after
src: './packages/ui',
Defensive patterns

Strategy: validation

Validate before calling

const canon = fs.realpathSync(path.resolve(cfg.src));
const common = fs.realpathSync(commonRoot);
if (!canon.startsWith(common + path.sep)) throw new Error(`src ${canon} is outside common root ${common}`);

Type guard

function isUnderRoot(child, root) { const c = path.resolve(child), r = path.resolve(root); return c === r || c.startsWith(r + path.sep); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02). Data as JSON: /api/errors/6ea0876a80485c99. Report an issue: GitHub.