facebook/relay · error
@__metadata directive expect only constant argument values.
Error message
@__metadata directive expect only constant argument values.
What it means
The @__metadata directive's single argument value must be a GraphQL constant (string, enum, etc.). build_internal_metadata_directives panics when the value is a variable or other non-constant Value, because metadata must be fully resolvable at compile time.
Source
Thrown at compiler/crates/relay-codegen/src/build_ast.rs:396
fn array(&mut self, array: Vec<Primitive>) -> AstKey {
self.ast_builder.intern(Ast::Array(array))
}
fn build_internal_metadata_directives(&mut self, directives: &[Directive]) -> Vec<ObjectEntry> {
directives
.iter()
.filter_map(|directive| {
if directive.name.item == *INTERNAL_METADATA_DIRECTIVE {
if directive.arguments.len() != 1 {
panic!("@__metadata directive should have only one argument!");
}
let arg = &directive.arguments[0];
let key = arg.name.item;
let value = match &arg.value.item {
Value::Constant(value) => self.build_constant_value(value),
_ => {
panic!("@__metadata directive expect only constant argument values.");
}
};
Some(ObjectEntry { key: key.0, value })
} else {
None
}
})
.collect()
}
fn use_exec_time_resolvers(&self, context: &ContextualMetadata) -> bool {
let feature_flags = &self.project_config.feature_flags;
feature_flags.enable_resolver_normalization_ast
|| (feature_flags.enable_exec_time_resolvers_directive
&& context.has_exec_time_resolvers_directive
&& !context.has_exec_time_resolvers_enabled_provider)
}View on GitHub (pinned to 668b1b85e0)
Solutions
- Replace the variable with a literal constant value in the @__metadata argument.
- Regenerate the fragment/operation through the compiler rather than hand-writing metadata.
- If tooling generates these directives, fix the generator to emit Value::Constant values only.
- Review Relay docs for the exact expected @__metadata argument shape (constant, single argument).
Example fix
// before
fragment FooResolver on Query @__metadata(parentType: $parent) { ... }
// after
fragment FooResolver on Query @__metadata(parentType: "Query") { ... }
Defensive patterns
Strategy: validation
Validate before calling
fn metadata_args_are_constant(d: &Directive) -> bool {
d.arguments.iter().all(|a| matches!(a.value.item, Value::Constant(_)))
}
Type guard
fn is_constant(v: &Value) -> bool { matches!(v.item, Value::Constant(_)) }
Try / catch
let result = std::panic::catch_unwind(|| build_internal_metadata_directives(&directives));
if result.is_err() { report("@__metadata argument must be a constant value"); }
Prevention
- Only use literal values in @__metadata arguments, never GraphQL variables.
- Add a lint rejecting variables inside compiler-internal directives.
- Fix code generators to emit constant values only.
When it happens
Trigger: Writing `@__metadata(parentType: $someVar)` or any variable/inline non-constant value; the match on Value::Constant falls through to the panic arm during build_fragment_metadata or build_request_parameters.
Common situations: Copy-pasting an argument with a variable from an operation into a @__metadata directive; tooling that injects variable references into metadata; misunderstanding that GraphQL variables aren't allowed in compiler-internal directives.
Related errors
- @__metadata directive should have only one argument!
- The {} argument in exec_time_resolvers directive should be t
- Expected at most one handle directive, got `{handle_field_di
- unknown @catch `to` value. Use `NULL` or `RESULT` (default)
- BabelPluginRelay: Expected exactly one definition per graphq
AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02).
Data as JSON: /api/errors/ce683f020e4391de.
Report an issue: GitHub.