facebook/flow · error

File_key: project_root has not been set

Error message

File_key: project_root has not been set

What it means

file_key keeps the project root in a process-global RwLock<Option<String>>; get_project_root panics via expect on None when set_project_root was never called. The comment states this is deliberate, following Hack's Relative_path convention: an unset root is a programmer error to crash on at the call site, not mask downstream. FileKey construction and path relativization all route through this getter.

Source

Thrown at rust_port/crates/flow_parser/src/file_key.rs:186

}

pub fn set_project_root(root: &str) {
    *PROJECT_ROOT.write().unwrap() = Some(enforce_trailing_slash(root));
}

pub fn set_flowlib_root(root: &str) {
    *FLOWLIB_ROOT.write().unwrap() = Some(enforce_trailing_slash(root));
}

// Retrieve a root, crashing immediately if not set. Following Hack's
// Relative_path convention: an unset root is a programmer error that
// should be caught at the call site, not masked downstream.
pub fn get_project_root() -> String {
    PROJECT_ROOT
        .read()
        .unwrap()
        .clone()
        .expect("File_key: project_root has not been set")
}

pub fn get_flowlib_root() -> String {
    FLOWLIB_ROOT
        .read()
        .unwrap()
        .clone()
        .expect("File_key: flowlib_root has not been set")
}

fn is_relative(path: &str) -> bool {
    std::path::Path::new(path).is_relative()
}

// libs, then source and json files at the same priority since JSON files are
// basically source files. We don't actually read resource files so they come
// last
fn order_of_inner(inner: &FileKeyInner) -> i32 {

View on GitHub (pinned to f88ac94bcf)

Solutions

  1. Call flow_parser::file_key::set_project_root at process start, before any FileKey use
  2. Centralize initialization in one init function invoked from main() and every test harness setup
  3. If embedding the crate, document set_project_root as a required first call

Example fix

// before — panics: root never set
let fk = FileKey::file_of(&source_path);

// after — initialize roots once at startup
fn init_roots(project_root: &Path, flowlib_root: &Path) {
    flow_parser::file_key::set_project_root(&project_root.to_string_lossy());
    flow_parser::file_key::set_flowlib_root(&flowlib_root.to_string_lossy());
}
// ...in main() / test setup, before any FileKey:
init_roots(&root, &flowlib);
let fk = FileKey::file_of(&source_path);
Defensive patterns

Strategy: validation

Validate before calling

// One-time init before any FileKey use (main + every test harness)
pub fn init_file_keys(project_root: &str, flowlib_root: &str) {
    flow_parser::file_key::set_project_root(project_root);
    flow_parser::file_key::set_flowlib_root(flowlib_root);
}

Prevention

When it happens

Trigger: A new binary, example, or test constructs FileKeys (file_of, or any path<->FileKey conversion) before any set_project_root call; a library consumer of flow_parser forgets initialization; a test harness lacks the setup fixture other suites provide.

Common situations: Adding a fresh integration test or small utility binary against the parser crate; refactoring init out of main; spawning worker processes that skip the normal startup sequence.

Related errors


AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20). Data as JSON: /api/errors/e3a716a6c5b230c8. Report an issue: GitHub.