{"record":{"id":"ead2e9cfcf3776b4","repo":"facebook/relay","slug":"unable-to-extract-module-name","errorCode":null,"errorMessage":"Unable to extract module name.","messagePattern":"Unable to extract module name\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/crates/relay-transforms/src/validations/validate_module_names.rs","lineNumber":35,"sourceCode":"use thiserror::Error;\n\npub fn validate_module_names(program: &Program) -> DiagnosticsResult<()> {\n    (ValidateModuleNames {}).validate_program(program)\n}\n\npub use extract_module_name::extract_module_name;\n\npub struct ValidateModuleNames {}\n\nimpl Validator for ValidateModuleNames {\n    const NAME: &'static str = \"ValidateModuleNames\";\n    const VALIDATE_ARGUMENTS: bool = false;\n    const VALIDATE_DIRECTIVES: bool = true;\n\n    fn validate_operation(&mut self, operation: &OperationDefinition) -> DiagnosticsResult<()> {\n        let operation_name = operation.name.item.0.to_string();\n        let path = operation.name.location.source_location().path();\n        let module_name = extract_module_name(path).expect(\"Unable to extract module name.\");\n        let (operation_type_suffix, pluralized_string) = match operation.kind {\n            OperationKind::Query => (\"Query\", \"Queries\"),\n            OperationKind::Mutation => (\"Mutation\", \"Mutations\"),\n            OperationKind::Subscription => (\"Subscription\", \"Subscriptions\"),\n        };\n\n        let operation_name_ending_is_valid = operation_name.ends_with(\"Query\")\n            || operation_name.ends_with(\"Mutation\")\n            || operation_name.ends_with(\"Subscription\");\n\n        if !operation_name.starts_with(&module_name) || !operation_name_ending_is_valid\n        // TODO: T71484519 re-enable this line when queries are correctly named in www\n        // || !operation_name.ends_with(operation_type_suffix)\n        {\n            return Err(vec![Diagnostic::error(\n                ValidationMessage::InvalidOperationName {\n                    pluralized_string: pluralized_string.to_string(),\n                    operation_type_suffix: operation_type_suffix.to_string(),","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-transforms/src/validations/validate_module_names.rs#L17-L53","documentation":"validate_operation extracts the module name from the operation's source file path (the camel-cased final path segment, used as the required name prefix for operations) and expects extraction to succeed. extract_module_name returns None when the path has no file stem or resolves to a bare index segment with no parent directory, so compiling documents without a usable file path panics.","triggerScenarios":"Compiling an operation from stdin, an in-memory document, or a path whose final segment is \"index\" with no enclosing directory (get_final_non_index_js_segment returns None), then having the module-name validation run.","commonSituations":"Tooling that feeds virtual documents (LSP scratch buffers, watchman-less ephemeral files) into the compiler; a query file literally named index.js/index.ts at a path the helper cannot resolve; operations generated without source locations.","solutions":["Compile operations from real files, not stdin/ephemeral buffers, when module-name validation is enabled.","Rename bare index.js operation files to a meaningful module name (e.g. UserProfile.js) so a module name can be extracted.","Disable/relax the module-name validation rule if your build uses virtual documents.","If index files are intentional, ensure they have a parent directory so the helper can fall back to it."],"exampleFix":"// before\nsrc/queries/index.js  // <- cannot derive module name\n// after\nsrc/queries/UserProfile.js with operation named UserProfileQuery","handlingStrategy":"validation","validationCode":"let module_name = extract_module_name(&path)\n    .ok_or_else(|| Diagnostic::error(format!(\"Cannot derive module name from path `{path}`; rename the file away from index.*\")))?;","typeGuard":"fn has_extractable_module_name(path: &str) -> bool { extract_module_name(path).is_some() }","tryCatchPattern":"let Some(module_name) = extract_module_name(path) else {\n    return Err(vec![Diagnostic::error(\"Unable to extract module name\")]);\n};","preventionTips":["Name operation files after the module (not index.js).","Compile from real file paths, not stdin/virtual buffers.","Keep operation names prefixed with the file's module name."],"tags":["relay-compiler","module-name","naming-convention"],"backgroundTag":"module-name-extraction-failed","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}