{"record":{"id":"215c02587e73a3db","repo":"cube-js/cube","slug":"pre-aggregation-tables-are-undefined","errorCode":null,"errorMessage":"Pre-aggregation tables are undefined.","messagePattern":"Pre-aggregation tables are undefined\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cubejs-query-orchestrator/src/orchestrator/PreAggregationLoadCache.ts","lineNumber":119,"sourceCode":"    if (this.tablePrefixes && client.getPrefixTablesQuery && this.preAggregations.options.skipExternalCacheAndQueue) {\n      return client.getPrefixTablesQuery(preAggregation.preAggregationsSchema, this.tablePrefixes);\n    }\n\n    return client.getTablesQuery(preAggregation.preAggregationsSchema);\n  }\n\n  public tablesCachePrefixKey(preAggregation: PreAggregationDescription) {\n    return this.queryCache.getKey('SQL_PRE_AGGREGATIONS_TABLES', `${preAggregation.dataSource}${preAggregation.preAggregationsSchema}${preAggregation.external ? '_EXT' : ''}`);\n  }\n\n  protected async getTablesQuery(preAggregation) {\n    const redisKey = this.tablesCachePrefixKey(preAggregation);\n    if (!this.tables[redisKey]) {\n      const tables = this.preAggregations.options.skipExternalCacheAndQueue && preAggregation.external ?\n        await this.fetchTablesNoCache(preAggregation) :\n        await this.tablesFromCache(preAggregation);\n      if (tables === undefined) {\n        throw new Error('Pre-aggregation tables are undefined.');\n      }\n      this.tables[redisKey] = tables;\n    }\n    return this.tables[redisKey];\n  }\n\n  public async getTableColumnTypes(preAggregation: PreAggregationDescription, tableName: string): Promise<TableStructure> {\n    const prefixKey = this.tablesCachePrefixKey(preAggregation);\n    if (!this.tableColumnTypes[prefixKey]?.[tableName]) {\n      if (!this.preAggregations.options.skipExternalCacheAndQueue && preAggregation.external) {\n        throw new Error(`Lambda union with source data feature is supported only by external rollups stored in Cube Store but was invoked for '${preAggregation.preAggregationId}'`);\n      }\n      const client = await this.externalDriverFactory();\n      const columnTypes = await client.tableColumnTypes(tableName);\n      if (!this.tableColumnTypes[prefixKey]) {\n        this.tableColumnTypes[prefixKey] = {};\n      }\n      this.tableColumnTypes[prefixKey][tableName] = columnTypes;","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-query-orchestrator/src/orchestrator/PreAggregationLoadCache.ts#L101-L137","documentation":"getTablesQuery resolves the set of pre-aggregation tables for a pre-aggregation, first from the in-memory tables cache and otherwise from cache driver or uncached fetch. If the lookup returns undefined (cache miss with a cache driver that failed to return data, or fetchTablesNoCache yielded nothing), the method throws rather than propagating undefined to versionEntries.","triggerScenarios":"versionEntries calls getTablesQuery for a pre-aggregation whose tables cache key is absent and where tablesFromCache/fetchTablesNoCache both return undefined — e.g. cache driver eviction/failure between fetchTables caching and reading, or a failed external fetch in skipExternalCacheAndQueue mode.","commonSituations":"Redis/memcached cache eviction or connectivity issues dropping pre-aggregation table entries; stale cache after deployments; external store unavailable while skipExternalCacheAndQueue bypasses the queued fetch path.","solutions":["Clear the orchestrator/query cache so tables are re-fetched (restart or flush cache driver)","Verify the cache driver (e.g. Redis) connectivity and persistence settings","Check the external store availability if the pre-aggregation is external; re-build/re-roll-up the pre-aggregation","Upgrade/patch if using skipExternalCacheAndQueue mode known to race with cache population"],"exampleFix":"// before\n// stale redis entry causes undefined tables\n// after\nawait orchestrator.queryCache.getCacheDriver().remove(keysPrefix); // flush stale entries, then re-run query","handlingStrategy":"retry","validationCode":"const key = loadCache.tablesCachePrefixKey(preAggregation);\nconst cached = loadCache.tables[key];\nif (cached === undefined) {\n  await loadCache.fetchTables(preAggregation); // warm the cache before reading\n}","typeGuard":"const tablesDefined = (t) => Array.isArray(t);","tryCatchPattern":"try {\n  return await loadCache.getTablesQuery(preAggregation);\n} catch (e) {\n  if (String(e.message).includes('Pre-aggregation tables are undefined')) {\n    await loadCache.fetchTables(preAggregation); // re-populate and retry once\n    return await loadCache.getTablesQuery(preAggregation);\n  }\n  throw e;\n}","preventionTips":["Monitor cache driver (Redis/memcached) availability and eviction policy","Warm the tables cache after deployments or cache flushes","Verify external store health when using skipExternalCacheAndQueue mode"],"tags":["query-orchestrator","pre-aggregations","cache","undefined"],"backgroundTag":"cache-miss-undefined-state","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}