facebook/relay · error
unexpected value for @stream if argument: {other:?}
Error message
unexpected value for @stream if argument: {other:?} What it means
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.
Source
Thrown at compiler/crates/relay-codegen/src/build_ast.rs:2018
kind: Primitive::String(CODEGEN_CONSTANTS.stream),
selections: next_selections,
}),
CodegenVariant::Normalization => {
let StreamDirective {
if_arg,
label_arg,
use_customized_batch_arg: _,
initial_count_arg: _,
} = StreamDirective::from(
stream,
&self.project_config.schema_config.defer_stream_interface,
);
let if_variable_name = if_arg.and_then(|arg| match &arg.value.item {
// `true` is the default, remove as the AST is typed just as a variable name string
// `false` constant values should've been transformed away in skip_unreachable_node
Value::Constant(ConstantValue::Boolean(true)) => None,
Value::Variable(var) => Some(var.name.item),
other => panic!("unexpected value for @stream if argument: {other:?}"),
});
let label_name = label_arg.unwrap().value.item.expect_string_literal();
self.object(object! {
if_: Primitive::string_or_null(if_variable_name.map(|variable_name| variable_name.0)),
kind: Primitive::String(CODEGEN_CONSTANTS.stream),
label: Primitive::String(label_name),
selections: next_selections,
})
}
})
}
// This function creates a node that is the UNION of the nodes that would be created for read time resolvers
// and for exec time resolvers (so runtime has ALL the information it needs to run for both resolver modes.)
// For C2C (client-to-client) edges, we emit ClientEdgeToClientObject with model resolvers.
// For C2S (client-to-server) edges, we emit ClientEdgeToServerObject with the operation reference.
fn build_client_edge_exec_and_read_time(
&mut self,View on GitHub (pinned to 668b1b85e0)
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.
Example fix
// before
fragment F on User @stream(if: false) { friends { name } }
// after
fragment F on User @stream(if: $shouldStream) { friends { name } } Defensive patterns
Strategy: validation
Validate before calling
function validateStreamIf(doc) {
visit(doc, {
Directive(node) {
if (node.name.value === 'stream') {
const ifArg = node.arguments.find(a => a.name.value === 'if');
if (ifArg && ifArg.value.kind !== 'Variable' &&
!(ifArg.value.kind === 'BooleanValue' && ifArg.value.value === true)) {
throw new Error('@stream if must be a variable or omitted');
}
}
}
});
} Type guard
function isValidStreamIf(value) {
return value == null ||
(value.kind === 'Variable') ||
(value.kind === 'BooleanValue' && value.value === true);
} Try / catch
try {
relayCompiler.compileAll();
} catch (e) {
if (String(e).includes('unexpected value for @stream if argument')) {
console.error('Fix @stream(if:...) usage:', e.message);
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- unexpected value for @defer if argument: {other:?}
- Unexpected custom directives: {:#?}
- Expected a scalar field.
- Expected filters_arg to have been previously validated.
- expected to find a supported argument as checked before
AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02).
Data as JSON: /api/errors/c88ccf50a5830473.
Report an issue: GitHub.