{"record":{"id":"d87aefbb325d3b4f","repo":"facebook/flow","slug":"file-key-flowlib-root-has-not-been-set","errorCode":null,"errorMessage":"File_key: flowlib_root has not been set","messagePattern":"File_key: flowlib_root has not been set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_parser/src/file_key.rs","lineNumber":194,"sourceCode":"}\n\n// Retrieve a root, crashing immediately if not set. Following Hack's\n// Relative_path convention: an unset root is a programmer error that\n// should be caught at the call site, not masked downstream.\npub fn get_project_root() -> String {\n    PROJECT_ROOT\n        .read()\n        .unwrap()\n        .clone()\n        .expect(\"File_key: project_root has not been set\")\n}\n\npub fn get_flowlib_root() -> String {\n    FLOWLIB_ROOT\n        .read()\n        .unwrap()\n        .clone()\n        .expect(\"File_key: flowlib_root has not been set\")\n}\n\nfn is_relative(path: &str) -> bool {\n    std::path::Path::new(path).is_relative()\n}\n\n// libs, then source and json files at the same priority since JSON files are\n// basically source files. We don't actually read resource files so they come\n// last\nfn order_of_inner(inner: &FileKeyInner) -> i32 {\n    match inner {\n        FileKeyInner::LibFile(_) => 1,\n        FileKeyInner::SourceFile(_) => 2,\n        FileKeyInner::JsonFile(_) => 2,\n        FileKeyInner::ResourceFile(_) => 3,\n    }\n}\n","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_parser/src/file_key.rs#L176-L212","documentation":"Same pattern as the project root: get_flowlib_root expects Some from the global FLOWLIB_ROOT RwLock and panics when set_flowlib_root was never called. The flowlib root anchors resolution of flowlib/ and tslib/ imports, so FileKey operations on lib files hit this getter immediately when uninitialized.","triggerScenarios":"Constructing or relativizing lib-file FileKeys (flowlib imports, tslib resolution) before set_flowlib_root; tests that set only the project root; binaries reusing parser APIs without the full startup sequence.","commonSituations":"New test binaries wired up with half the initialization; refactors that dropped the flowlib setup call; embedding flow_parser where the caller only configured a project root.","solutions":["Call set_flowlib_root right after set_project_root in the shared init function","Add a startup assertion (call get_flowlib_root once at boot) so misconfiguration fails fast with your own message","Review every binary/test entry point after moving initialization code"],"exampleFix":"// before — panics: flowlib root never set\nlet fk = FileKey::flowlib_file(&name);\n\n// after — set both roots during startup\nflow_parser::file_key::set_project_root(&format!(\"{}/\", root.display()));\nflow_parser::file_key::set_flowlib_root(&flowlib_dir.to_string_lossy());\nlet fk = FileKey::flowlib_file(&name);","handlingStrategy":"validation","validationCode":"// Both roots, one init — call before creating any FileKey\npub fn init_file_keys(project_root: &str, flowlib_root: &str) {\n    flow_parser::file_key::set_project_root(project_root);\n    flow_parser::file_key::set_flowlib_root(flowlib_root);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set flowlib_root together with project_root in the shared init function","Exercise get_flowlib_root during startup to surface misconfiguration immediately","Audit test harnesses that only configure one of the two roots"],"tags":["rust","global-state","initialization","programmer-error","flowlib"],"backgroundTag":"uninitialized-global-state","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","contentChangedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}