facebook/relay · error

Expected an IR that models a field

Error message

Expected an IR that models a field

What it means

expect_field_ir unwraps a DocblockIr and panics unless it is the Field variant. A docblock expected to describe a resolver field produced some other IR (e.g. Type), so the field-extraction invariant was violated.

Source

Thrown at compiler/crates/relay-compiler/src/build_project/build_resolvers_schema/extract_docblock_ir.rs:168

            .map(|docblock_ir| {
                let ir = expect_field_ir(docblock_ir);
                AllocatedDocblockIr { ir, is_base }
            })
            .collect(),
    })
}

fn expect_type_ir(docblock_ir: relay_docblock::DocblockIr) -> ResolverTypeDocblockIr {
    match docblock_ir {
        DocblockIr::Type(ir) => ir,
        _ => panic!("Expected an IR that models a type"),
    }
}

fn expect_field_ir(docblock_ir: relay_docblock::DocblockIr) -> ResolverFieldDocblockIr {
    match docblock_ir {
        DocblockIr::Field(ir) => ir,
        _ => panic!("Expected an IR that models a field"),
    }
}

struct ResolverSchemaDocuments<'a> {
    type_asts: TypeAsts,
    field_asts_and_definitions: FieldAstsAndDefinitions<'a>,
}
struct TypeAsts(Vec<DocblockAST>);
struct FieldAstsAndDefinitions<'a>(
    FxHashMap<&'a PathBuf, (Vec<DocblockAST>, Option<&'a Vec<ExecutableDefinition>>)>,
);

fn extract_schema_documents_for_resolvers<'a>(
    project_name: &'a ProjectName,
    compiler_state: &'a CompilerState,
    graphql_asts_map: &'a FnvHashMap<ProjectName, GraphQLAsts>,
) -> DiagnosticsResult<ResolverSchemaDocuments<'a>> {
    let docblock_ast_sources = (

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Move the docblock onto the field/function declaration it describes
  2. Verify the docblock tags indicate a field (e.g. @RelayResolver with a return type) not a type definition
  3. Check Relay version migration notes for docblock IR classification changes
Defensive patterns

Strategy: type-guard

Validate before calling

if let DocblockIr::Field(_) = docblock_ir {
    let field_ir = expect_field_ir(docblock_ir);
}

Type guard

fn as_field_ir(ir: DocblockIr) -> Option<ResolverFieldDocblockIr> {
    match ir {
        DocblockIr::Field(f) => Some(f),
        _ => None,
    }
}

Try / catch

// not catchable; use as_field_ir and report a diagnostic naming the docblock source location

Prevention

When it happens

Trigger: ExtractedDocblockIr processes a field docblock (e.g. @RelayResolver on a function/property) but the docblock compiles to DocblockIr::Type or another non-field variant.

Common situations: A type-level docblock placed on a field, or a resolver file whose docblocks were reordered/renamed after a Relay version change, changing IR classification.

Related errors


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