cube-js/cube · error

No pre-aggregation partitions were built yet for the…

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

When externalRefresh is enabled, this API instance only reads pre-aggregation partitions built by a refresh worker; it never builds them itself. loadPreAggregation throws this when no version entry matching the pre-aggregation's structure version exists (i.e., no partitions built yet) and throwOnMissingPartition is set, telling the user their refresh worker setup isn't producing the expected tables.

Solutions

  1. Ensure the refresh worker is running (scheduledInvoker / dbScheduling or external cron calling the refresh API) and building this pre-aggregation.
  2. Match all refresh settings: timezone, refreshKey, partition granularity and pre-aggregation definition must be identical between refresh worker and API instance.
  3. Check the store: built partition tables should exist in the shared external store; list tables and compare against the expected table name patterns in the message.
  4. Temporarily rebuild the pre-aggregation (buildRollup/pre-aggregations API) to confirm partitions can be produced, then inspect for definition drift.
  5. Disable throwOnMissingPartition or externalRefresh only if you intend this instance to build pre-aggregations itself.

Example fix

// before (querying before any build)
cubejsServer.event('rollupOnly')
// after: run a refresh worker that builds first
scheduledRefreshContexts / refreshWorker: { enabled: true } // then query
Defensive patterns

Strategy: try-catch

Validate before calling

// before querying, confirm partitions exist in the external store
const tables = await externalDriver.tables();
const hasPartition = tables.some(t => t.startsWith(expectedTablePrefix));
if (externalRefresh && !hasPartition) throw new Error('No partitions built yet: run refresh worker first');

Try / catch

try {
  return await preAggregations.loadPreAggregation({...});
} catch (e) {
  if (String(e.message).includes('No pre-aggregation partitions were built yet')) {
    // trigger refresh worker / inform user to configure refresh
    throw new Error('Configure and run your refresh worker, then retry the query.');
  }
  throw e;
}

Prevention

When it happens

Trigger: Query executed against an API instance with externalRefresh=true before any refresh worker has built the pre-aggregation; structureVersion mismatch (pre-aggregation definition/timezone changed after partitions were built); refresh worker not running or building into a different store.

Common situations: Deploying the API with externalRefresh enabled but forgetting to schedule the refresh worker; refresh settings (timezone, refreshKey, date range) differing from the query's; rollup definition changed so built partitions no longer match the expected structure version; pre-aggregation tables exist under different names than the expected patterns.

Related errors


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

Appendix: source

Thrown at packages/cubejs-query-orchestrator/src/orchestrator/PreAggregationLoader.ts:171

          ? this.preAggregationQueryKey(refreshKeyValues)
          : undefined,
      };
    } else {
      // Serve whatever version already exists rather than making this request wait for a build
      const structureVersion = getStructureVersion(this.preAggregation);
      const getVersionsStarted = new Date();
      const { byStructure } = await this.loadCache.getVersionEntries(this.preAggregation);
      this.logger('Load PreAggregations Tables', {
        preAggregation: this.preAggregation,
        requestId: this.requestId,
        duration: (new Date().getTime() - getVersionsStarted.getTime())
      });

      const versionEntryByStructureVersion = byStructure[`${this.preAggregation.tableName}_${structureVersion}`];
      if (this.externalRefresh) {
        if (!versionEntryByStructureVersion && throwOnMissingPartition) {
          // eslint-disable-next-line no-use-before-define
          throw new Error(PreAggregations.noPreAggregationPartitionsBuiltMessage([this.preAggregation]));
        }
        if (!versionEntryByStructureVersion) {
          return null;
        } else {
          // the rollups are being maintained independently of this instance of cube.js
          // immediately return the latest rollup data that instance already has
          return {
            targetTableName: this.targetTableName(versionEntryByStructureVersion),
            refreshKeyValues: [],
            lastUpdatedAt: versionEntryByStructureVersion.last_updated_at,
            buildRangeEnd: versionEntryByStructureVersion.build_range_end,
          };
        }
      }

      if (versionEntryByStructureVersion) {
        // this triggers an asynchronous/background load of the pre-aggregation but immediately
        // returns the latest data it already has

View on GitHub (pinned to 7d981676b3)