facebook/relay · error

expected to find a supported argument as checked before

Error message

expected to find a supported argument as checked before

What it means

transform_linked_field in the @match transform assumes the field it is rewriting was already confirmed (via has_match_supported_arg) to carry the 'supported' argument, so it force-unwraps the lookup of MATCH_CONSTANTS.supported_arg. The expect fires when that argument is missing at this point — an invariant violation meaning the pre-check and the argument rewrite are out of sync.

Source

Thrown at compiler/crates/relay-transforms/src/match_/hash_supported_argument.rs:76

        if !self.has_match_supported_arg(field) {
            return transformed_field;
        }

        let mut new_field = match transformed_field {
            Transformed::Keep => Arc::new(field.clone()),
            Transformed::Replace(Selection::LinkedField(linked_field)) => linked_field,
            Transformed::Delete | Transformed::Replace(_) => {
                panic!(
                    "unexpected transformed_field in HashSupportedArgumentTransform: {transformed_field:?}"
                )
            }
        };

        let supported_arg = Arc::make_mut(&mut new_field)
            .arguments
            .iter_mut()
            .find(|arg| arg.name.item == MATCH_CONSTANTS.supported_arg)
            .expect("expected to find a supported argument as checked before");

        let mut input = String::new();
        match &supported_arg.value.item {
            Value::Constant(ConstantValue::List(items)) => {
                for item in items {
                    if let ConstantValue::String(name) = item {
                        input.push('\0');
                        input.push_str(name.lookup());
                    } else {
                        panic!("expected all supported arguments to be strings, as verified above");
                    }
                }
            }
            Value::Constant(ConstantValue::String(name)) => {
                // Single item lists can be written without the list wrapper per GraphQL spec
                input.push('\0');
                input.push_str(name.lookup());
            }

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Verify has_match_supported_arg returned true for this exact field and that both checks see the same field definition.
  2. Run transforms in the documented order so the supported argument exists before transform_linked_field executes.
  3. Make sure the field's arguments are mutated in place on the same Field that gets compiled, not lost through cloning a stale structure.
  4. Confirm MATCH_CONSTANTS.supported_arg matches the argument name actually declared in your schema.
  5. Reproduce with a minimal @match fragment and file an issue with the compiler version if the invariant still breaks.

Example fix

// before (schema): field used with @match declares no supported argument
type Query { viewer: User }
// after
type Query {
  viewer(supportedLocales: [Language!]): User
}
Defensive patterns

Strategy: validation

Validate before calling

function fieldHasSupportedArg(schema, fieldName, argName) {
  const f = schema.getType('Query')?.getFields?.()[fieldName.split('.').pop()];
  return Boolean(f && f.args && f.args.some(a => a.name === argName));
}
// before compiling:
// if (!fieldHasSupportedArg(schema, 'Query.viewer', 'supportedLocales')) throw ...

Type guard

function isMatchSupportedField(field, argName) {
  return Boolean(
    field.arguments?.some(a => a.name === argName) &&
    field.schemaDefinition?.arguments?.named?.(argName)
  );
}

Try / catch

try {
  program = applyMatchTransform(program);
} catch (e) {
  if (String(e.message).includes('supported argument as checked before')) {
    logInvariantViolation('match transform ran without prior supported-arg insertion');
  }
  throw e;
}

Prevention

When it happens

Trigger: A linked field is transformed for @match but its arguments contain no argument named MATCH_CONSTANTS.supported_arg — e.g. the supported-argument insertion step was skipped, ran on a different copy of the field, or the Arc::make_mut mutation landed on a stale clone.

Common situations: Custom compiler pipelines chaining match_ transforms out of order; transforms operating on cloned Program/Field structures so mutations never reach the compiled field; mixing relay-transforms crate versions where the supported_arg name changed.

Related errors


AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02). Data as JSON: /api/errors/1094c84adb3b2fad. Report an issue: GitHub.