SigNoz/signoz · error

unsupported aggregate operator %s

Error message

unsupported aggregate operator %s

What it means

The aggregation switch in buildTracesQuery (v4) handles a fixed set of aggregate operators (count, count_distinct, rate/sum/avg variants, etc.); anything else falls to default and is rejected. This is the last-resort guard for aggregate operators that passed earlier panel-type checks.

Source

Thrown at pkg/query-service/app/traces/v4/query_builder.go:457

				subQuery, err := existsSubQueryForFixedColumn(mq.AggregateAttribute, v3.FilterOperatorExists)
				if err == nil {
					filterSubQuery = fmt.Sprintf("%s AND %s", filterSubQuery, subQuery)
				}
			} else {
				cType := getClickHouseTracesColumnType(mq.AggregateAttribute.Type)
				cDataType := getClickHouseTracesColumnDataType(mq.AggregateAttribute.DataType)
				filterSubQuery = fmt.Sprintf("%s AND mapContains(%s_%s, '%s')", filterSubQuery, cType, cDataType, mq.AggregateAttribute.Key)
			}
		}
		op := "toFloat64(count())"
		query := fmt.Sprintf(queryTmpl, op, filterSubQuery, groupBy, having, orderBy)
		return query, nil
	case v3.AggregateOperatorCountDistinct:
		op := fmt.Sprintf("toFloat64(count(distinct(%s)))", aggregationKey)
		query := fmt.Sprintf(queryTmpl, op, filterSubQuery, groupBy, having, orderBy)
		return query, nil
	default:
		return "", fmt.Errorf("unsupported aggregate operator %s", mq.AggregateOperator)
	}
}

// PrepareTracesQuery returns the query string for traces
// start and end are in epoch millisecond
// step is in seconds
func PrepareTracesQuery(start, end int64, panelType v3.PanelType, mq *v3.BuilderQuery, options v3.QBOptions) (string, error) {
	// adjust the start and end time to the step interval
	if panelType == v3.PanelTypeGraph {
		// adjust the start and end time to the step interval for graph panel types
		start = start - (start % (mq.StepInterval * 1000))
		end = end - (end % (mq.StepInterval * 1000))
	}
	if options.GraphLimitQtype == constants.FirstQueryGraphLimit {
		// give me just the group by names
		query, err := buildTracesQuery(start, end, mq.StepInterval, mq, panelType, options)
		if err != nil {
			return "", err

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Use a supported traces aggregate operator (count, count_distinct, sum, avg, min, max, rate variants, etc.)
  2. Compute quantiles via a ClickHouse query builder expression instead
  3. Align frontend and query-service versions

Example fix

// before
mq.AggregateOperator = "p95"

// after
mq.AggregateOperator = v3.AggregateOperatorAvg
Defensive patterns

Strategy: validation

Validate before calling

var supportedAggs = map[v3.AggregateOperator]bool{v3.AggregateOperatorCount: true, v3.AggregateOperatorCountDistinct: true /* etc. */}
if !supportedAggs[mq.AggregateOperator] {
    return fmt.Errorf("aggregate %s unsupported for traces", mq.AggregateOperator)
}

Type guard

func isTraceAggregate(op v3.AggregateOperator) bool {
    switch op {
    case v3.AggregateOperatorCount, v3.AggregateOperatorCountDistinct:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Setting mq.AggregateOperator to an operator not implemented in the v4 traces aggregation switch (e.g. quantiles like p95, or an empty string) on a non-no-op traces query.

Common situations: Frontends exposing the full metrics operator set (including quantiles) for traces; custom clients sending arbitrary operator strings; version mismatch where newer operators aren't implemented server-side.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/4c629b37278d9bee. Report an issue: GitHub.