{"record":{"id":"c95ce7e20712800e","repo":"cube-js/cube","slug":"clickhouse-doesn-t-support-pre-aggregations-withou","errorCode":null,"errorMessage":"ClickHouse doesn't support pre-aggregations without indexes","messagePattern":"ClickHouse doesn't support pre-aggregations without indexes","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-schema-compiler/src/adapter/ClickHouseQuery.ts","lineNumber":237,"sourceCode":"      datesTo.push(to);\n    });\n\n    return `SELECT parseDateTimeBestEffort(arrayJoin(['${datesFrom.join('\\',\\'')}'])) as date_from, parseDateTimeBestEffort(arrayJoin(['${datesTo.join('\\',\\'')}'])) as date_to`;\n  }\n\n  public concatStringsSql(strings) {\n    // eslint-disable-next-line prefer-template\n    return 'toString(' + strings.join(') || toString(') + ')';\n  }\n\n  public unixTimestampSql() {\n    return `toUnixTimestamp(${this.nowTimestampSql()})`;\n  }\n\n  public preAggregationLoadSql(cube, preAggregation, tableName) {\n    const sqlAndParams = this.preAggregationSql(cube, preAggregation);\n    if (!preAggregation.indexes) {\n      throw new UserError('ClickHouse doesn\\'t support pre-aggregations without indexes');\n    }\n    const firstIndexName = Object.keys(preAggregation.indexes)[0];\n    const indexColumns = this.evaluateIndexColumns(cube, preAggregation.indexes[firstIndexName]);\n    return [`CREATE TABLE ${tableName} ENGINE = MergeTree() ORDER BY (${indexColumns.join(', ')}) ${this.asSyntaxTable} ${sqlAndParams[0]}`, sqlAndParams[1]];\n  }\n\n  public countDistinctApprox(sql: string): string {\n    return `uniq(${sql})`;\n  }\n\n  public createIndexSql(indexName, tableName, escapedColumns) {\n    return `ALTER TABLE ${tableName} ADD INDEX ${indexName} (${escapedColumns.join(', ')}) TYPE minmax GRANULARITY 1`;\n  }\n\n  public dimensionColumns(cubeAlias) {\n    // For the top-level SELECT statement, explicitly set the column alias.\n    // Clickhouse sometimes includes the \"q_0\" prefix in the column name, and this\n    // leads to errors during the result mapping.","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-schema-compiler/src/adapter/ClickHouseQuery.ts#L219-L255","documentation":"ClickHouse pre-aggregation tables are created as MergeTree tables whose ORDER BY key comes from the first defined index. Without any indexes there is no sort key, so ClickHouseQuery.preAggregationLoadSql throws this UserError before generating CREATE TABLE SQL.","triggerScenarios":"Defining a pre-aggregation in a data model without an `indexes` property (or with empty indexes) while using the ClickHouse driver, then triggering pre-aggregation load/rollup.","commonSituations":"Copying pre-aggregation configs from Postgres/MySQL projects (where indexes are optional) into a ClickHouse project; forgetting to add an index after renaming one; schema generators that omit indexes.","solutions":["Add an `indexes` block to the pre-aggregation (e.g. `indexes: { main: { columns: [CUBE.dimensionOrMeasure] } }`).","Use an `indexColumns`-compatible primary index matching your common filter/groupBy columns.","If no index is desired, switch that rollup to a database that supports indexless pre-aggregations."],"exampleFix":"// before\npreAggregations: {\n  main: {\n    measures: [CUBE.count],\n    timeDimension: CUBE.createdAt,\n    granularity: `day`\n  }\n}\n// after\npreAggregations: {\n  main: {\n    measures: [CUBE.count],\n    timeDimension: CUBE.createdAt,\n    granularity: `day`,\n    indexes: { mainIdx: { columns: [CUBE.createdAt] } }\n  }\n}","handlingStrategy":"validation","validationCode":"if (dbType === 'clickhouse' && preAggregation && !preAggregation.indexes) {\n  throw new Error('ClickHouse pre-aggregation requires indexes');\n}","typeGuard":null,"tryCatchPattern":"try { await cube.refresh() } catch (e) { if (/pre-aggregations without indexes/.test(e.message)) { console.error('Add an indexes block to cube', e.message); } else throw e; }","preventionTips":["Always define an index on ClickHouse pre-aggregations","Lint data models for ClickHouse-specific requirements","Run refresh/pre-aggregation build in CI to catch config errors"],"tags":["clickhouse","pre-aggregation","indexes","user-error"],"backgroundTag":"pre-aggregation-missing-index","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}