cube-js/cube · error · Error
${this.constructor} driver supports only rows upload
Error message
${this.constructor} driver supports only rows upload What it means
uploadTableWithIndexes() only supports table data supplied as in-memory rows (isDownloadTableMemoryData). If tableData is a stream-based or reference-based (e.g. unload-to-S3) form, the driver throws this error.
Source
Thrown at packages/cubejs-base-driver/src/BaseDriver.ts:489
public param(_paramIndex: number): string {
return '?';
}
public testConnectionTimeout() {
return this.testConnectionTimeoutValue;
}
public async downloadTable(table: string, _options: ExternalDriverCompatibilities): Promise<TableMemoryData> {
return { rows: await this.query(`SELECT * FROM ${table}`) };
}
public async uploadTable(table: string, columns: TableStructure, tableData: DownloadTableData) {
return this.uploadTableWithIndexes(table, columns, tableData, [], null, [], {});
}
public async uploadTableWithIndexes(table: string, columns: TableStructure, tableData: DownloadTableData, indexesSql: IndexesSQL, _uniqueKeyColumns: string[] | null, _queryTracingObj: any, _externalOptions: ExternalCreateTableOptions) {
if (!isDownloadTableMemoryData(tableData)) {
throw new Error(`${this.constructor} driver supports only rows upload`);
}
await this.createTable(table, columns);
try {
if (isDownloadTableMemoryData(tableData)) {
for (let i = 0; i < tableData.rows.length; i++) {
await this.query(
`INSERT INTO ${table}
(${columns.map(c => this.quoteIdentifier(c.name)).join(', ')})
VALUES (${columns.map((c, paramIndex) => this.param(paramIndex)).join(', ')})`,
columns.map(c => this.toColumnValue(tableData.rows[i][c.name] as string, c.type))
);
}
for (let i = 0; i < indexesSql.length; i++) {
const [query, params] = indexesSql[i].sql;
await this.query(query, params);
}
}View on GitHub (pinned to 7d981676b3)
Solutions
- Materialize the data into rows before uploading (fetch stream fully and pass { rows })
- Use a driver/storage-fs path that supports the given data form (e.g. CSV unload/ingest instead of row upload)
- Convert remote CSV files to rows via downloadQueryResults or CSV parsing
- Check which DownloadTableData variant the target driver supports
Example fix
// before
target.uploadTable('tbl', cols, unloadedCsvRef); // stream/ref form
// after
const rows = await parseCsvToRows(unloadedCsvRef);
target.uploadTable('tbl', cols, { rows }); Defensive patterns
Strategy: type-guard
Validate before calling
import { isDownloadTableMemoryData } from '@cubejs-backend/base-driver';
if (!isDownloadTableMemoryData(tableData)) throw new Error('Driver needs rows: materialize before upload'); Type guard
function isRowUploadData(d: DownloadTableData): d is DownloadTableMemoryData {
return Array.isArray((d as any).rows);
} Try / catch
try {
await target.uploadTable(table, cols, data);
} catch (e) {
if (/supports only rows upload/.test(e.message)) {
const rows = await materializeToRows(data);
await target.uploadTable(table, cols, { rows });
} else throw e;
} Prevention
- Always materialize streams/remote refs to rows before row-based uploads
- Check target driver capabilities when designing cross-driver copy flows
- Centralize a data-shape adapter between unload results and uploads
- Document which DownloadTableData variant each driver accepts
When it happens
Trigger: Calling uploadTable()/uploadTableWithIndexes() with DownloadTableData that contains streams or remote file references instead of a rows array.
Common situations: Copying unload results (e.g. from BigQuery unload producing CSV URLs) into a driver that only accepts row arrays, or passing streamed query results between drivers.
Related errors
- Driver's .streamQuery() method is not implemented yet.
- Error during upload of ${fileName} create table: ${createTab
- CUBEJS_DB_NAME can`t be empty.
- Please specify CUBEJS_DB_URL
- You are using an old version of Druid. Unable to detect colu
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/f055a6189cf587b9.
Report an issue: GitHub.