facebook/relay · error

Unable to get current working directory.

Error message

Unable to get current working directory.

What it means

get_config resolves the relay config either from an explicit path or by searching from the current working directory. When no config path is given, current_dir() is unwrapped with .expect(); if the process's working directory cannot be determined (typically because the directory was deleted or is unreadable), it panics with 'Unable to get current working directory.'

Source

Thrown at compiler/crates/relay-bin/src/main.rs:399

            handle_regenerate_subschema_command(command).await
        }
        Commands::ExperimentalCompareDocumentIR(command) => {
            handle_compare_document_ir_command(command)
        }
        #[cfg(unix)]
        Commands::Server(opt) => handle_server_command(opt).await,
    };

    if let Err(err) = result {
        error!("{}", err);
        std::process::exit(1);
    }
}

fn get_config(config_path: Option<PathBuf>) -> Result<Config, Error> {
    match config_path {
        Some(config_path) => Config::load(config_path).map_err(Error::ConfigError),
        None => Config::search(&current_dir().expect("Unable to get current working directory."))
            .map_err(Error::ConfigError),
    }
}

/// Wire up the OSS CLI's default config extensions: the standard operation
/// persister (Remote/Local from `project_config.persist`) and the default
/// extra-artifacts generator. Used by every entry point that drives a real
/// build.
fn apply_default_cli_extensions(config: &mut Config) {
    config.create_operation_persister = Some(Box::new(|project_config| {
        project_config.persist.as_ref().map(
            |persist_config| -> Box<dyn OperationPersister + Send + Sync> {
                match persist_config {
                    PersistConfig::Remote(remote_config) => {
                        Box::new(RemotePersister::new(remote_config.clone()))
                    }
                    PersistConfig::Local(local_config) => {
                        Box::new(LocalPersister::new(local_config.clone()))

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Run relay from an existing directory, or pass --config so current_dir() is never consulted
  2. Recreate/re-enter the directory: `cd /valid/path && relay build`
  3. In scripts, verify the working directory exists before invoking relay
  4. Pass an explicit config path in CI: `relay build --config "$PWD/relay.config.js"`

Example fix

// before
rm -rf build && cd build && relay build   // cwd deleted -> panic
// after
relay build --config ./relay.config.js    // from a live directory
Defensive patterns

Strategy: validation

Validate before calling

const cwd = process.cwd();
const fs = require('fs');
if (!fs.existsSync(cwd)) throw new Error('Working directory no longer exists; re-enter it or pass --config.');

Try / catch

try {
  await relay(['build']);
} catch (e) {
  if (/Unable to get current working directory/.test(e.message)) {
    console.error('Your cwd was deleted; cd into a valid dir or pass --config.');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling any command path that calls get_config (codemod, regenerate-subschema, compiler/LSP commands, foreground server) without --config while current_dir() returns Err.

Common situations: Running relay from a directory that was deleted (common in CI workspaces cleaned mid-run); running with cwd pointing at a removed mount; scripts cd-ing into temp dirs that are subsequently wiped.

Related errors


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