hasura/graphql-engine · error · InternalDeveloperError

The aggregation function {aggregation_function} was used on

Error message

The aggregation function {aggregation_function} was used on the model object type and not on a model field. Aggregation functions operate on columns, not rows

What it means

An aggregation function was applied at the model object-type level instead of on a model field. Aggregations operate on columns (field values), not rows, so aggregating the object itself is meaningless and rejected during IR resolution.

Source

Thrown at v3/crates/graphql/ir/src/error.rs:239

    #[error(
        "The aggregation function {aggregation_function} operating over the {aggregate_operand_type} type is missing a data connector mapping for {data_connector_name}"
    )]
    DataConnectorAggregationFunctionNotFound {
        aggregate_operand_type: QualifiedTypeName,
        aggregation_function: AggregationFunctionName,
        data_connector_name: Qualified<DataConnectorName>,
    },

    #[error(
        "A field ({field_name}) with an AggregatableField annotation was found on a scalar-typed ({aggregate_operand_type}) operand's selection set"
    )]
    AggregatableFieldFoundOnScalarTypedOperand {
        field_name: FieldName,
        aggregate_operand_type: QualifiedTypeName,
    },

    #[error(
        "The aggregation function {aggregation_function} was used on the model object type and not on a model field. Aggregation functions operate on columns, not rows"
    )]
    ColumnAggregationFunctionUsedOnModelObjectType {
        aggregate_operand_type: QualifiedTypeName,
        aggregation_function: AggregationFunctionName,
    },

    #[error("{0}")]
    PlanInternalDeveloperError(plan::InternalDeveloperError),
}

#[derive(Debug, thiserror::Error)]
pub enum InternalEngineError {
    #[error("serialization error: {0}")]
    SerializationError(#[from] json::Error),

    #[error("error from normalized AST: {0}")]
    IRConversionError(#[from] gql::normalized_ast::Error),

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Move the aggregation function under a specific field/column of the model
  2. Use the generated *_aggregate query structure as a template
  3. Check the aggregate query shape in the docs for your model

Example fix

# before
query { songs { agg { avg } } }
# after
query { songs_aggregate { agg { avg { duration } } } }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure aggregations are applied to a field, not the model node
assert(aggregateTarget.kind === 'field');

Type guard

const isFieldLevelAggregation = (node) => node.path.at(-1)?.kind === 'field';

Try / catch

// On error, rewrite query so the aggregation sits under a specific column

Prevention

When it happens

Trigger: Placing an aggregation like count/sum directly on the model type node rather than under a field in an aggregate query; malformed aggregate queries from hand-built query strings.

Common situations: Misunderstanding the aggregate query shape and nesting the aggregation one level too high; migrating handwritten queries from another GraphQL dialect with different aggregate syntax.

Related errors


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