nocobase/nocobase · error · FlowSurfaceBadRequestError

chart query.sorting does not support aggregated measure outp

Error message

chart query.sorting does not support aggregated measure outputs or custom measure aliases in builder mode

What it means

In builder mode, runtime sorting cannot target aggregated measure outputs or custom measure aliases because the aggregation happens after row-level data is fetched, so the runtime cannot order by those computed columns. The validator builds a set of unsupported measure output aliases (unsupportedMeasureOutputs) and rejects any sorting item referencing them.

Source

Thrown at packages/plugins/@nocobase/plugin-flow-engine/src/server/flow-surfaces/chart-config.ts:1211

    return;
  }

  const unsupportedMeasureOutputs = new Set<string>();
  for (const measure of _.castArray(query?.measures || [])) {
    const outputAlias = aliasOfSelection(measure);
    const rawFieldAlias = aliasOfFieldValue(measure?.field);
    if (!outputAlias) {
      continue;
    }
    if (measure?.aggregation || (rawFieldAlias && outputAlias !== rawFieldAlias)) {
      unsupportedMeasureOutputs.add(outputAlias);
    }
  }

  for (const item of sorting) {
    const sortingField = aliasOfFieldValue(item?.field);
    if (sortingField && unsupportedMeasureOutputs.has(sortingField)) {
      throw new FlowSurfaceBadRequestError(
        'chart query.sorting does not support aggregated measure outputs or custom measure aliases in builder mode',
      );
    }
  }
}

function normalizeBuilderQuery(query: Record<string, any>) {
  const resource = normalizeMergedChartResource(query, { required: true });
  const dimensions = _.isUndefined(query.dimensions)
    ? undefined
    : Array.isArray(query.dimensions)
      ? query.dimensions.map((item, index) => normalizeChartDimension(item, index))
      : (() => {
          throw new FlowSurfaceBadRequestError('chart query.dimensions must be an array');
        })();
  const measures = Array.isArray(query.measures)
    ? query.measures
        .map((item, index) => normalizeChartMeasure(item, index))

View on GitHub (pinned to fa42722fef)

Solutions

  1. Remove the sorting entry that references the aggregated measure and sort client-side after data retrieval.
  2. Sort by a dimension instead (e.g. by the category/date field) if the business goal allows.
  3. If aggregate sorting is essential, switch the chart query to mode='sql' where ORDER BY on aggregates is supported.

Example fix

// before
measures: [{ field: 'amount', aggregate: 'sum', alias: 'total' }], sorting: [{ field: 'total' }]
// after
measures: [{ field: 'amount', aggregate: 'sum', alias: 'total' }]
// no sorting; sort rows in the client after fetching
Defensive patterns

Strategy: validation

Validate before calling

function validateNoAggregatedSorting(query) {
  const aggregatedAliases = new Set(
    query.measures.filter((m) => m.aggregate || m.alias !== m.field).map((m) => m.alias || m.field),
  );
  for (const item of query.sorting || []) {
    if (aggregatedAliases.has(item.field)) {
      throw new Error(`cannot sort by aggregated measure '${item.field}' in builder mode`);
    }
  }
}

Type guard

function isSortableMeasure(m: { aggregate?: string; alias?: string; field: string }): boolean {
  return !m.aggregate && (m.alias ?? m.field) === m.field;
}

Try / catch

try {
  return await runChartQuery(query);
} catch (err) {
  if (err?.message?.includes('aggregated measure outputs')) {
    const safe = { ...query, sorting: (query.sorting || []).filter((s) => !isMeasureAlias(query, s.field)) };
    return runChartQuery(safe);
  }
  throw err;
}

Prevention

When it happens

Trigger: A builder-mode chart query with measures that aggregate (sum/count/avg etc.) or define custom aliases, combined with query.sorting whose field alias matches one of those aggregated/custom measure outputs.

Common situations: Trying to sort a bar chart descending by a summed revenue measure; sorting by a count(*) alias; templates migrated from SQL-mode charts where ORDER BY on aggregates was legal.

Related errors


AI-assisted analysis of nocobase/nocobase@fa42722fef (2026-09-01). Data as JSON: /api/errors/4f91379db748d299. Report an issue: GitHub.