{"record":{"id":"a6cd3ab80dd7c8a2","repo":"apache/superset","slug":"when-using-group-by-you-are-limited-to-use-a-sin","errorCode":null,"errorMessage":"When using 'Group By' you are limited to use a single metric","messagePattern":"When using 'Group By' you are limited to use a single metric","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"superset-frontend/src/visualizations/TimeTable/config/buildQuery.ts","lineNumber":36,"sourceCode":" */\nimport { t } from '@apache-superset/core/translation';\nimport {\n  buildQueryContext,\n  ensureIsArray,\n  QueryFormData,\n} from '@superset-ui/core';\n\n/**\n * Mirrors the legacy TimeTableViz.query_obj: a timeseries query ordered\n * by the first metric (ascending unless order_desc), limited to a single\n * metric when grouped.\n */\nexport default function buildQuery(formData: QueryFormData) {\n  const { order_desc, groupby } = formData;\n  return buildQueryContext(formData, baseQueryObject => {\n    const metrics = ensureIsArray(baseQueryObject.metrics);\n    if (ensureIsArray(groupby).length > 0 && metrics.length > 1) {\n      throw new Error(\n        t(\"When using 'Group By' you are limited to use a single metric\"),\n      );\n    }\n    const firstMetric = metrics[0];\n    return [\n      {\n        ...baseQueryObject,\n        is_timeseries: true,\n        orderby: firstMetric ? [[firstMetric, !order_desc]] : undefined,\n      },\n    ];\n  });\n}\n","sourceCodeStart":18,"sourceCodeEnd":50,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset-frontend/src/visualizations/TimeTable/config/buildQuery.ts#L18-L50","documentation":"The Time-table chart's buildQuery enforces a legacy constraint from TimeTableViz.query_obj: when a Group By dimension is set, the query may only aggregate a single metric. With groupby present and more than one metric selected the client-side query builder aborts before any request is sent.","triggerScenarios":"In Explore, adding a dimension to Group By while Metrics contains 2+ entries on a Time-table chart; loading/importing a saved Time-table chart whose form_data has both multiple metrics and a non-empty groupby.","commonSituations":"Copying form_data from a Pivot/Table chart into Time-table; dashboards imported from older versions where validation was looser; editing an existing Time-table and adding a second metric without removing Group By.","solutions":["Remove the Group By entry, or reduce Metrics to exactly one metric.","If multiple metrics per group are needed, switch to a Pivot Table or Table chart.","Fix imported chart JSON: set metrics to a single entry before loading the dashboard.","Add a control-level warning in a custom plugin fork so users see the constraint before save."],"exampleFix":"// before (form_data)\n\"metrics\": [\"sum__sales\", \"avg__price\"],\n\"groupby\": [\"region\"]\n\n// after\n\"metrics\": [\"sum__sales\"],\n\"groupby\": [\"region\"]","handlingStrategy":"validation","validationCode":"import { ensureIsArray } from '@superset-ui/core';\n\nfunction isValidTimeTableForm(formData: QueryFormData): boolean {\n  const grouped = ensureIsArray(formData.groupby).length > 0;\n  const metricCount = ensureIsArray(formData.metrics).length;\n  return !grouped || metricCount <= 1;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await buildQuery(formData);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('single metric')) {\n    setControlValue('metrics', [currentFirstMetric]); // auto-repair\n    return;\n  }\n  throw e;\n}","preventionTips":["When a Time-table chart sets Group By, immediately limit the Metrics control to one entry in Explore.","Validate imported chart JSON for the metrics+groupby constraint before saving.","Document that multi-metric grouped tables belong to Pivot Table, not Time-table."],"tags":["visualization","time-table","query-builder","form-data"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}