{"record":{"id":"e1c5dd63a31549f2","repo":"cube-js/cube","slug":"unable-to-import-as-rows-in-cube-store-empty-co","errorCode":null,"errorMessage":"Unable to import (as rows) in Cube Store: empty columns. Most probably, introspection has failed.","messagePattern":"Unable to import \\(as rows\\) in Cube Store: empty columns\\. Most probably, introspection has failed\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cubejs-cubestore-driver/src/CubeStoreDriver.ts","lineNumber":295,"sourceCode":"      await this.importStreamingSource(columns, tableData, table, indexes, uniqueKeyColumns, queryTracingObj, externalOptions?.sealAt);\n    } else if (tableData.rows) {\n      await this.importRows(table, columns, indexes, aggregations, tableData, queryTracingObj);\n    } else {\n      throw new Error(`Unsupported table data passed to ${this.constructor}`);\n    }\n  }\n\n  private createIndexString(index: CreateTableIndex) {\n    const prefix = {\n      regular: '',\n      aggregate: 'AGGREGATE '\n    }[index.type] || '';\n    return `${prefix}INDEX ${index.indexName} (${index.columns.join(',')})`;\n  }\n\n  private async importRows(table: string, columns: Column[], indexesSql: any, aggregations: any, tableData: DownloadTableMemoryData, queryTracingObj?: any) {\n    if (!columns || columns.length === 0) {\n      throw new Error('Unable to import (as rows) in Cube Store: empty columns. Most probably, introspection has failed.');\n    }\n\n    await this.createTableWithOptions(table, columns, { indexes: indexesSql, aggregations, buildRangeEnd: queryTracingObj?.buildRangeEnd }, queryTracingObj);\n    try {\n      const batchSize = 2000; // TODO make dynamic?\n      for (let j = 0; j < Math.ceil(tableData.rows.length / batchSize); j++) {\n        const currentBatchSize = Math.min(tableData.rows.length - j * batchSize, batchSize);\n        const indexArray = Array.from({ length: currentBatchSize }, (v, i) => i);\n        const valueParamPlaceholders =\n          indexArray.map(i => `(${columns.map((c, paramIndex) => this.param(paramIndex + i * columns.length)).join(', ')})`).join(', ');\n        const params = indexArray.map(i => columns\n          .map(c => this.toColumnValue(tableData.rows[i + j * batchSize][c.name], c.type)))\n          .reduce((a, b) => a.concat(b), []);\n\n        await this.query(\n          `INSERT INTO ${table}\n        (${columns.map(c => this.quoteIdentifier(c.name)).join(', ')})\n        VALUES ${valueParamPlaceholders}`,","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-cubestore-driver/src/CubeStoreDriver.ts#L277-L313","documentation":"When importing pre-aggregation data as in-memory rows, CubeStoreDriver requires a non-empty columns array to build CREATE TABLE. Empty columns means the introspection step that derives columns from the query result failed or returned nothing.","triggerScenarios":"uploadTable called with tableData.rows but columns=[] or null — usually when the schema compiler could not infer columns for the pre-aggregation (e.g. failed introspection query, empty result metadata).","commonSituations":"Broken schema (measures/dimensions resolving to no columns); DB driver returning empty column metadata; serialization mismatch after upgrading packages.","solutions":["Fix the data model so introspection produces columns (valid measures/dimensions in the rollup).","Check the source driver returns column metadata for the introspection query.","Verify columns array is populated before uploadTable (add an assertion).","Upgrade cubejs packages to aligned versions and retry the pre-aggregation build."],"exampleFix":"// before\nawait driver.uploadTable('preagg', [], { rows });\n// after\nif (!columns.length) throw new Error('introspection produced no columns');\nawait driver.uploadTable('preagg', columns, { rows });","handlingStrategy":"validation","validationCode":"if (!Array.isArray(columns) || columns.length === 0) {\n  throw new Error('Refusing to upload: introspection produced no columns');\n}\nawait driver.uploadTable(table, columns, { rows });","typeGuard":"function hasColumns(c: unknown): c is Array<{ name: string; type: string }> {\n  return Array.isArray(c) && c.length > 0 && c.every(col => typeof (col as any).name === 'string');\n}","tryCatchPattern":"try {\n  await driver.uploadTable(table, columns, { rows });\n} catch (e) {\n  if (e.message.includes('empty columns')) {\n    console.error('Introspection failed: check data model measures/dimensions and source driver metadata');\n  }\n  throw e;\n}","preventionTips":["Verify pre-aggregation definitions compile and reference existing measures/dimensions.","Test introspection against the source DB in dev before production builds.","Assert columns non-empty at the boundary before uploadTable.","Keep cubejs-schema-compiler and drivers up to date."],"tags":["cubestore","introspection","pre-aggregation"],"backgroundTag":"empty-columns-introspection-failed","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}