SigNoz/signoz · error
multiple orderBy criteria are not supported for trace querie
Error message
multiple orderBy criteria are not supported for trace queries
What it means
buildTracesQuery (v4) with AggregateOperator=no-op and panelType=trace builds a single ORDER BY clause for the trace list SQL; more than one orderBy entry cannot be expressed and is rejected.
Source
Thrown at pkg/query-service/app/traces/v4/query_builder.go:314
filterSubQuery = filterSubQuery + " AND " + spanScopeSubQuery
}
// timerange will be sent in epoch millisecond
selectLabels := getSelectLabels(mq.GroupBy)
if selectLabels != "" {
selectLabels = selectLabels + ","
}
orderBy := orderByAttributeKeyTags(panelType, mq.OrderBy, mq.GroupBy)
if orderBy != "" {
orderBy = " order by " + orderBy
}
if mq.AggregateOperator == v3.AggregateOperatorNoOp {
var query string
if panelType == v3.PanelTypeTrace {
if len(mq.OrderBy) > 1 {
return "", fmt.Errorf("multiple orderBy criteria are not supported for trace queries")
}
orderBySpanCount := false
// Check if orderBy contains a specific reference to span_count
if len(mq.OrderBy) == 1 && mq.OrderBy[0].ColumnName == constants.OrderBySpanCount {
orderBySpanCount = true
}
if !orderBySpanCount {
withSubQuery := fmt.Sprintf(constants.TracesExplorerViewSQLSelectWithSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3_LOCAL_TABLENAME, timeFilter)
afterSubQuery := tracesV3.AddLimitToQuery(constants.TracesExplorerViewSQLSelectAfterSubQuery, mq.Limit)
if mq.Offset != 0 {
afterSubQuery = tracesV3.AddOffsetToQuery(afterSubQuery, mq.Offset)
}
query = fmt.Sprintf(constants.TracesExplorerViewSQLSelectBeforeSubQuery, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3, timeFilter, filterSubQuery) + withSubQuery + ")" + afterSubQuery
} else {
withSubQueryWithLimits := tracesV3.AddLimitToQuery(constants.TracesExplorerSpanCountWithSubQuery, mq.Limit)
withSubQuery := fmt.Sprintf(withSubQueryWithLimits, constants.SIGNOZ_TRACE_DBNAME, constants.SIGNOZ_SPAN_INDEX_V3_LOCAL_TABLENAME, timeFilter, filterSubQuery)
afterSubQuery := tracesV3.AddLimitToQuery(constants.TraceExplorerSpanCountAfterSubQuery, mq.Limit)View on GitHub (pinned to 5069bf80b0)
Solutions
- Reduce orderBy to a single column for trace list queries
- Keep only the user's primary sort and drop secondary sorts client-side
Example fix
// before
mq.OrderBy = []v3.OrderBy{{ColumnName:"timestamp", Order:"desc"},{ColumnName:"duration_ns", Order:"desc"}}
// after
mq.OrderBy = []v3.OrderBy{{ColumnName:"timestamp", Order:"desc"}} Defensive patterns
Strategy: validation
Validate before calling
if panelType == v3.PanelTypeTrace && mq.AggregateOperator == v3.AggregateOperatorNoOp && len(mq.OrderBy) > 1 {
mq.OrderBy = mq.OrderBy[:1] // keep primary sort
} Type guard
func isSingleOrderBy(mq *v3.BuilderQuery) bool { return len(mq.OrderBy) <= 1 } Prevention
- Enforce single-sort UI for trace list panels
- Trim secondary sorts before serializing the query
When it happens
Trigger: A traces list (PanelTypeTrace) no-op query whose mq.OrderBy array contains 2 or more items.
Common situations: UI sends default timestamp ordering plus a user-added sort; copying a list panel's orderBy from another panel type that allows multi-sort.
Related errors
- unsupported operation, exists and not exists can only be app
- unsupported operator %s
- invalid scope item type: %s
- select columns cannot be empty for panelType %s
- operator %s not supported
AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28).
Data as JSON: /api/errors/de1199062f0778f3.
Report an issue: GitHub.