{"record":{"id":"c88ccf50a5830473","repo":"facebook/relay","slug":"unexpected-value-for-stream-if-argument-other","errorCode":null,"errorMessage":"unexpected value for @stream if argument: {other:?}","messagePattern":"unexpected value for @stream if argument: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/crates/relay-codegen/src/build_ast.rs","lineNumber":2018,"sourceCode":"                kind: Primitive::String(CODEGEN_CONSTANTS.stream),\n                selections: next_selections,\n            }),\n            CodegenVariant::Normalization => {\n                let StreamDirective {\n                    if_arg,\n                    label_arg,\n                    use_customized_batch_arg: _,\n                    initial_count_arg: _,\n                } = StreamDirective::from(\n                    stream,\n                    &self.project_config.schema_config.defer_stream_interface,\n                );\n                let if_variable_name = if_arg.and_then(|arg| match &arg.value.item {\n                    // `true` is the default, remove as the AST is typed just as a variable name string\n                    // `false` constant values should've been transformed away in skip_unreachable_node\n                    Value::Constant(ConstantValue::Boolean(true)) => None,\n                    Value::Variable(var) => Some(var.name.item),\n                    other => panic!(\"unexpected value for @stream if argument: {other:?}\"),\n                });\n                let label_name = label_arg.unwrap().value.item.expect_string_literal();\n                self.object(object! {\n                     if_: Primitive::string_or_null(if_variable_name.map(|variable_name| variable_name.0)),\n                     kind: Primitive::String(CODEGEN_CONSTANTS.stream),\n                     label: Primitive::String(label_name),\n                     selections: next_selections,\n                 })\n            }\n        })\n    }\n\n    // This function creates a node that is the UNION of the nodes that would be created for read time resolvers\n    // and for exec time resolvers (so runtime has ALL the information it needs to run for both resolver modes.)\n    // For C2C (client-to-client) edges, we emit ClientEdgeToClientObject with model resolvers.\n    // For C2S (client-to-server) edges, we emit ClientEdgeToServerObject with the operation reference.\n    fn build_client_edge_exec_and_read_time(\n        &mut self,","sourceCodeStart":2000,"sourceCodeEnd":2036,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-codegen/src/build_ast.rs#L2000-L2036","documentation":"This panic fires during codegen of a @stream directive. The compiler requires the `if` argument of @stream to be either the constant `true` (default, dropped) or a variable name; any other value shape after earlier transforms is unexpected and indicates an untransformed or malformed @stream argument.","triggerScenarios":"Compiling a document with `@stream(if: false)` (constant false should have been removed by skip_unreachable_node) or with a non-variable/non-boolean `if` argument (string, enum, object literal).","commonSituations":"Feeding raw documents with literal `@stream(if: false)` to the compiler; mismatched compiler version where the constant-condition transform no longer runs; code generators emitting @stream with hardcoded if values.","solutions":["Use `@stream` without `if` for unconditional streaming, or `@stream(if: $variable)` with a Boolean variable.","Verify skip_unreachable_node and related transforms execute before build_ast; upgrade/align relay compiler versions across your toolchain.","Add validation to reject constant `if` values on @stream at document-validation time.","Fix any custom codegen or template tooling to emit variable-based `if` arguments only."],"exampleFix":"// before\nfragment F on User @stream(if: false) { friends { name } }\n\n// after\nfragment F on User @stream(if: $shouldStream) { friends { name } }","handlingStrategy":"validation","validationCode":"function validateStreamIf(doc) {\n  visit(doc, {\n    Directive(node) {\n      if (node.name.value === 'stream') {\n        const ifArg = node.arguments.find(a => a.name.value === 'if');\n        if (ifArg && ifArg.value.kind !== 'Variable' &&\n            !(ifArg.value.kind === 'BooleanValue' && ifArg.value.value === true)) {\n          throw new Error('@stream if must be a variable or omitted');\n        }\n      }\n    }\n  });\n}","typeGuard":"function isValidStreamIf(value) {\n  return value == null ||\n    (value.kind === 'Variable') ||\n    (value.kind === 'BooleanValue' && value.value === true);\n}","tryCatchPattern":"try {\n  relayCompiler.compileAll();\n} catch (e) {\n  if (String(e).includes('unexpected value for @stream if argument')) {\n    console.error('Fix @stream(if:...) usage:', e.message);\n  } else throw e;\n}","preventionTips":["Omit `if` on @stream for unconditional streaming","Use Boolean variables for conditional @stream","Verify constant-condition transforms run before codegen","Lint documents for literal boolean if arguments"],"tags":["relay-compiler","graphql","stream-directive","panic"],"backgroundTag":"invalid-directive-argument","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}