{"record":{"id":"0ea29a13bd11e693","repo":"cube-js/cube","slug":"this-constructor-driver-supports-only-rows-uplo-0ea29a","errorCode":null,"errorMessage":"${this.constructor} driver supports only rows upload","messagePattern":"(.+?) driver supports only rows upload","errorType":"exception","errorClass":"PostgresError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-postgres-driver/src/PostgresDriver.ts","lineNumber":489,"sourceCode":"    return this.tableColumnTypesWithPrecision(table);\n  }\n\n  protected override toGenericType(columnType: string, precision?: number | null, scale?: number | null): GenericDataBaseType {\n    return PostgresToGenericType[columnType.toLowerCase()] || super.toGenericType(columnType, precision, scale);\n  }\n\n  public readOnly() {\n    return !!this.config.readOnly;\n  }\n\n  public async uploadTableWithIndexes(\n    table: string,\n    columns: TableStructure,\n    tableData: DownloadTableMemoryData,\n    indexesSql: IndexesSQL\n  ) {\n    if (!tableData.rows) {\n      throw new PostgresError(`${this.constructor} driver supports only rows upload`);\n    }\n\n    await this.createTable(table, columns);\n\n    try {\n      await this.query(\n        `INSERT INTO ${table}\n      (${columns.map(c => this.quoteIdentifier(c.name)).join(', ')})\n      SELECT * FROM UNNEST (${columns.map((c, columnIndex) => `${this.param(columnIndex)}::${this.fromGenericType(c.type)}[]`).join(', ')})`,\n        columns.map(c => tableData.rows.map(r => r[c.name]))\n      );\n\n      for (let i = 0; i < indexesSql.length; i++) {\n        const [query, p] = indexesSql[i].sql;\n        await this.query(query, p);\n      }\n    } catch (e) {\n      await this.dropTable(table);","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-postgres-driver/src/PostgresDriver.ts#L471-L507","documentation":"PostgresDriver.uploadTableWithIndexes only supports uploading data held in memory as rows. If the DownloadTableMemoryData passed in has no 'rows' array (e.g. it only holds a CSV file reference or other lazy form), the driver throws because it cannot stream non-row data into PostgreSQL.","triggerScenarios":"Calling uploadTableWithIndexes (directly or via the pre-aggregation upload pipeline) with tableData whose rows property is undefined/null — e.g. data downloaded in a non-row format or an incompatible driver produced the DownloadTableMemoryData.","commonSituations":"Custom or misconfigured download drivers returning data without materialized rows; rolling up pre-aggregations across drivers where the source driver's unload output is passed to the Postgres driver; older code paths that populate DownloadTableMemoryData differently.","solutions":["Ensure the data source populates tableData.rows before calling uploadTableWithIndexes","Use a download/driver pipeline that produces in-memory rows (e.g. DownloadTableMemoryData with rows loaded)","If using unload/CSV flows, use a driver path that supports them instead of the rows-only Postgres upload"],"exampleFix":"// before\nawait driver.uploadTableWithIndexes(table, columns, { files: csvFiles }, indexes);\n// after\nconst tableData = await sourceDriver.downloadTable(table); // materializes rows\nawait driver.uploadTableWithIndexes(table, columns, tableData, indexes);","handlingStrategy":"validation","validationCode":"function assertRowsUpload(tableData) {\n  if (!tableData || !Array.isArray(tableData.rows)) {\n    throw new Error('uploadTableWithIndexes requires DownloadTableMemoryData with rows');\n  }\n}\nassertRowsUpload(tableData);","typeGuard":"const hasRows = (td) => typeof td === 'object' && td !== null && Array.isArray(td.rows) && td.rows.length >= 0;","tryCatchPattern":"try {\n  await driver.uploadTableWithIndexes(table, columns, tableData, indexes);\n} catch (e) {\n  if (String(e.message).includes('supports only rows upload')) {\n    tableData = await sourceDriver.downloadTable(table); // materialize rows\n    await driver.uploadTableWithIndexes(table, columns, tableData, indexes);\n  } else throw e;\n}","preventionTips":["Ensure the download step materializes rows before uploading to Postgres","Don't pass CSV-file-based DownloadTableMemoryData to the Postgres driver","Test pre-aggregation upload flows end-to-end after changing source drivers"],"tags":["postgres","upload","pre-aggregations","data-format"],"backgroundTag":"unsupported-upload-format","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}