cube-js/cube · error

No pre-aggregation partitions were built yet for the pre-agg

Error message

No pre-aggregation partitions were built yet for the pre-aggregation serving this query and this API instance wasn't set up to build pre-aggregations. Please make sure your refresh worker is configured correctly, running, pre-aggregation tables are built and all pre-aggregation refresh settings like timezone match. Expected table name patterns: ${expectedTableNames.join(', ')}

What it means

In PreAggregationPartitionRangeLoader.loadPreAggregations, when externalRefresh is true the instance only serves partitions built by the refresh worker. If the loaded results list is empty (no partitions found for any partition loader), it throws the same 'no partitions built yet' guidance message, listing the expected table name patterns so the user can compare against what was actually built.

Source

Thrown at packages/cubejs-query-orchestrator/src/orchestrator/PreAggregationPartitionRangeLoader.ts:255

            ...result,
            partitionRange: partitionRanges[i]
          };
        }));
        return { loadResults: resolveResults.filter(res => res !== null), partitionLoaders };
      };

      // eslint-disable-next-line prefer-const
      let loadResultAndLoaders = await loadPreAggregationsByPartitionRanges(await this.partitionRanges());
      if (this.options.externalRefresh && loadResultAndLoaders.loadResults.length === 0) {
        loadResultAndLoaders = await loadPreAggregationsByPartitionRanges(await this.partitionRanges(true));
        // In case there are no partitions ready at matched time dimension intersection then no data can be retrieved.
        // We need to provide any table so query can just execute successfully.
        if (loadResultAndLoaders.loadResults.length > 0) {
          loadResultAndLoaders.loadResults = [loadResultAndLoaders.loadResults[loadResultAndLoaders.loadResults.length - 1]];
        }
      }
      if (this.options.externalRefresh && loadResultAndLoaders.loadResults.length === 0) {
        throw new Error(
          // eslint-disable-next-line no-use-before-define
          PreAggregations.noPreAggregationPartitionsBuiltMessage(loadResultAndLoaders.partitionLoaders.map(p => p.preAggregation))
        );
      }

      let { loadResults } = loadResultAndLoaders;

      let lambdaTable: InlineTable;
      let emptyResult = false;

      if (this.preAggregation.rollupLambdaId) {
        if (this.lambdaQuery && loadResults.length > 0) {
          const { buildRangeEnd, targetTableName } = loadResults[loadResults.length - 1];
          const lambdaTypes = await this.loadCache.getTableColumnTypes(this.preAggregation, targetTableName);
          lambdaTable = await this.downloadLambdaTable(buildRangeEnd, lambdaTypes);
        }
        const rollupLambdaResults = this.preAggregationsTablesToTempTables.filter(tempTableResult => tempTableResult[1].rollupLambdaId === this.preAggregation.rollupLambdaId);
        const filteredResults = loadResults.filter(

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Verify the refresh worker is configured and running, and that it built partitions covering the queried range.
  2. Compare the expected table name patterns in the error with actual tables in the store; rebuild if definitions changed.
  3. Ensure timezone and dateRangeAlign/granularity settings match between the refresh worker and queries.
  4. Expand the query's date range to intersect built partitions, or configure the worker to build through now.
  5. Set externalRefresh=false on this instance if it should build pre-aggregations on demand instead.

Example fix

// before
checkAuthLock: query with externalRefresh and no worker
// after
// schedule refresh in cube.js server
app.listen(...); // plus
preAggregationsSchema: [{ ... scheduledRefresh: true }] and running refresh worker
Defensive patterns

Strategy: try-catch

Validate before calling

const tables = await externalDriver.tables();
const expected = expectedTableNames();
if (externalRefresh && !expected.some(p => tables.some(t => t.startsWith(p)))) {
  throw new Error('Refresh worker has not built partitions for this query range');
}

Try / catch

try {
  return await partitionRangeLoader.loadPreAggregations();
} catch (e) {
  if (String(e.message).includes('No pre-aggregation partitions were built yet')) {
    // ensure refresh worker coverage for the query's date range, then retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: Querying a partitioned pre-aggregation with externalRefresh=true when the refresh worker hasn't built any matching partitions; all built partitions are outside the query's date range; expected table names differ due to timezone/granularity/definition drift.

Common situations: Refresh worker missing/misconfigured in serverless deployments; query time range extending beyond built partitions (e.g., querying today when worker builds only through yesterday); mismatched timezone settings between build and query; new pre-aggregation added but never built.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/1ec3099abbff2452. Report an issue: GitHub.