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.'

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.

Appendix: 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)