facebook/relay · error

Expected to have a reader operation for `{normal_name}`

Error message

Expected to have a reader operation for `{normal_name}`

What it means

expect_reader unwraps the optional reader operation of an operation group and panics if it is None. An artifact typed as Operation or UpdatableQuery requires a reader AST; its absence means grouping produced an inconsistent entry.

Source

Thrown at compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs:357

impl OperationGroup<'_> {
    fn new() -> Self {
        OperationGroup {
            normalization: None,
            operation_text: None,
            reader: None,
            typegen: None,
        }
    }

    fn expect_reader(&self) -> Arc<OperationDefinition> {
        let normal_name = self
            .normalization
            .map_or("MISSING_ENTRY", |n| n.name.item.0.lookup());

        Arc::clone(
            self.reader.unwrap_or_else(|| {
                panic!("Expected to have a reader operation for `{normal_name}`")
            }),
        )
    }

    fn expect_typegen(&self) -> Arc<OperationDefinition> {
        let normal_name = self
            .normalization
            .map_or("MISSING_ENTRY", |n| n.name.item.0.lookup());

        Arc::clone(
            self.typegen.unwrap_or_else(|| {
                panic!("Expected to have a typegen operation for `{normal_name}`")
            }),
        )
    }
}

/// Groups operations from the given programs by name for efficient access.

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Clear generated files and recompile from scratch
  2. Check that @updatable and reader-affecting directives are used per current Relay docs
  3. Create a minimal repro and file a Relay compiler issue with the operation name from the panic message
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure a reader AST exists before rendering the artifact
if (artifact.reader == null) {
  throw new Error(`Operation ${artifact.normalization?.name ?? 'MISSING_ENTRY'} lacks a reader AST`);
}

Type guard

fn has_reader(a: &ArtifactContent) -> bool { a.reader.is_some() }

Try / catch

try {
  renderArtifact(group);
} catch (panic) {
  if (/Expected to have a reader operation/.test(String(panic))) {
    recompileFromCleanState();
  } else throw panic;
}

Prevention

When it happens

Trigger: ArtifactContent::Operation or ArtifactContent::UpdatableQuery rendering calls expect_reader on a group where self.reader is None while a normalization AST exists (normal_name is used in the message, or MISSING_ENTRY if absent).

Common situations: Relay compiler bug after an upgrade, or an operation whose reader AST was dropped by an earlier transform (e.g. @updatable misconfiguration).

Related errors


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