hasura/graphql-engine · error · ObjectTypesIssue

Recursive reference detected for object type '{type_name}' t

Error message

Recursive reference detected for object type '{type_name}' through non-null field path: {field_path}

What it means

A cycle was detected in object type fields where every field along the path is non-null: an object type transitively contains itself through required (non-null) fields. Such layouts cannot be represented (they imply infinite nesting) and resolution aborts.

Source

Thrown at v3/crates/metadata-resolve/src/stages/object_types/types.rs:484

    #[error(
        "the field {field_name:} in {type_name:} should have the type {expected:} for data connector {data_connector:} but the field has type {provided:}"
    )]
    FieldTypeMismatch {
        field_name: FieldName,
        type_name: Qualified<CustomTypeName>,
        data_connector: Qualified<DataConnectorName>,
        expected: QualifiedTypeName,
        provided: QualifiedTypeName,
    },
    #[error(
        "Field type {field_type} could not be found in field {field_name} for object type {object_type_name}"
    )]
    FieldTypeNotFound {
        field_type: Qualified<CustomTypeName>,
        object_type_name: Qualified<CustomTypeName>,
        field_name: FieldName,
    },
    #[error(
        "Recursive reference detected for object type '{type_name}' through non-null field path: {field_path}"
    )]
    RecursiveObjectType {
        type_name: Qualified<CustomTypeName>,
        field_path: String,
    },
    #[error(
        "The field '{field_name}' in object type '{type_name}' cannot be mapped to data connector '{data_connector}' field '{data_connector_object}.{data_connector_column}' because: {issue}"
    )]
    FieldTypeNdcMappingIssue {
        field_name: FieldName,
        type_name: Qualified<CustomTypeName>,
        data_connector: Qualified<DataConnectorName>,
        data_connector_object: DataConnectorObjectType,
        data_connector_column: DataConnectorColumnName,
        issue: TypeCompatibilityIssue,
    },
}

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Make at least one field in the cycle nullable (remove the non-null/! marker on that field)
  2. Restructure the model to break the cycle (e.g. represent one side as a relationship instead of a required nested field)
  3. Use an explicit relationship with argument mapping instead of a direct nested non-null object field

Example fix

// before
{"name":"parent","type":"Category!"} // in Category itself
// after
{"name":"parent","type":"Category"} // nullable breaks the cycle
Defensive patterns

Strategy: validation

Validate before calling

// Build a nullability-aware graph and reject non-null cycles
function hasNonNullCycle(types) {
  const g = buildNonNullGraph(types); // edge only for non-null object fields
  return detectCycle(g);
}
if (hasNonNullCycle(objectTypes)) throw new Error('Non-null recursive object type');

Prevention

When it happens

Trigger: Type A has a non-null field of type B, and B has a non-null field of type A (or A → A directly); nullable fields would be fine, but the non-null chain creates the invalid recursion.

Common situations: Modeling bidirectional relationships (parent/child, author/posts) with required fields on both sides; self-referencing structures like trees with a required 'parent' field.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/40382be140fef087. Report an issue: GitHub.