{"record":{"id":"8c0aedbeadbac4b9","repo":"facebook/relay","slug":"expected-condition-with-static-value-to-have-been","errorCode":null,"errorMessage":"Expected Condition with static value to have been pruned or inlined.","messagePattern":"Expected Condition with static value to have been pruned or inlined\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/crates/relay-codegen/src/build_ast.rs","lineNumber":2471,"sourceCode":"                        aliased_fragment\n                    }\n                } else {\n                    primitive\n                }\n            }\n        }\n    }\n\n    fn build_condition(\n        &mut self,\n        context: &mut ContextualMetadata,\n        condition: &Condition,\n    ) -> Primitive {\n        let selections = self.build_selections(context, condition.selections.iter());\n        Primitive::Key(self.object(object! {\n            condition: Primitive::String(match &condition.value {\n                ConditionValue::Variable(variable) => variable.name.item.0,\n                ConditionValue::Constant(_) => panic!(\n                    \"Expected Condition with static value to have been pruned or inlined.\"\n                ),\n            }),\n            kind: Primitive::String(CODEGEN_CONSTANTS.condition_value),\n            passing_value: Primitive::Bool(condition.passing_value),\n            selections: selections,\n        }))\n    }\n\n    pub fn build_operation_variable_definitions(\n        &mut self,\n        variable_definitions: &[VariableDefinition],\n    ) -> AstKey {\n        let var_defs = variable_definitions\n            .iter()\n            .map(|def| {\n                let default_value = if let Some(const_val) = &def.default_value {\n                    self.build_constant_value(&const_val.item)","sourceCodeStart":2453,"sourceCodeEnd":2489,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-codegen/src/build_ast.rs#L2453-L2489","documentation":"Relay's codegen builder converts an @include/@skip directive condition into a serialized Primitive for the generated AST. By this point in the pipeline, any Condition whose value is a compile-time constant must have already been pruned (directive statically false) or inlined into the selection (statically true) by earlier normalization passes. Hitting Constant means a condition with a static value survived into key building, which the compiler considers a bug in earlier passes or an unsupported directive placement.","triggerScenarios":"Building the primitive for a @skip or @include directive whose `if:` argument is a literal (e.g. `@skip(if: true)` or `@skip(if: false)`) instead of a variable; a compiler pass that failed to prune/inline such conditions before build_primitive_for_key runs.","commonSituations":"Hand-written GraphQL documents using static @skip/@include arguments; older or patched compiler pipelines where pruning/normalization was skipped or a new pass inserted conditions without simplifying constants; test fixtures with literal directive args.","solutions":["Replace static @skip/@include arguments with a variable, e.g. `field @skip(if: $shouldSkip)`, and pass the variable at runtime","Remove the statically-valued @skip/@include directive entirely and add/remove the field in the document (or use `@required`/fragment composition) as appropriate","Update the Relay Compiler so constant conditions are pruned/inlined; if using a custom pass, ensure it runs normalization that simplifies constant conditions before codegen","If it appears to be a compiler bug (variable was intended), file a reduced reproduction against relay compiler"],"exampleFix":"// before\nquery { user { name @skip(if: false) email @include(if: true) } }\n// after\nquery($showEmail: Boolean!) { user { name email @include(if: $showEmail) } }","handlingStrategy":"validation","validationCode":"// Before compiling, scan documents for static directive args:\nfunction hasStaticSkipInclude(doc) {\n  const bad = [];\n  visit(doc, {\n    Directive(node) {\n      if ((node.name.value === 'skip' || node.name.value === 'include') &&\n          node.arguments?.some(a => a.value.kind !== 'Variable')) {\n        bad.push(node.name.value);\n      }\n    }\n  });\n  return bad.length === 0;\n}\nif (!hasStaticSkipInclude(queryDoc)) throw new Error('Use variables with @skip/@include');","typeGuard":"function isVariableCondition(value) {\n  return typeof value === 'object' && value !== null && 'variableName' in value;\n}","tryCatchPattern":"try {\n  compiled = compile(queryText);\n} catch (e) {\n  if (String(e).includes('pruned or inlined')) {\n    // rewrite static @skip/@include to variables and retry\n  }\n  throw e;\n}","preventionTips":["Always pass @skip/@include conditions via GraphQL variables, never literals","Run a document lint that rejects literal @skip/@include args in CI","Keep the Relay compiler up to date so pruning/normalization runs","Test hand-written documents through the compiler pipeline before shipping"],"tags":["compiler","graphql","codegen","directives"],"backgroundTag":"unpruned-static-directive-condition","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}