cube-js/cube · error · Error
You are using an old version of Druid. Unable to detect colu
Error message
You are using an old version of Druid. Unable to detect column types in readOnly mode.
What it means
downloadQueryResults() relies on the x-druid-sql-header-included header (Druid 0.22+ SQL API) to return column metadata. If the response has no columns, the driver cannot map column types in readOnly mode and throws, indicating the Druid version is too old to supply type information.
Source
Thrown at packages/cubejs-druid-driver/src/DruidDriver.ts:148
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('INFORMATION_SCHEMA', 'sys')
`;
}
public async createSchemaIfNotExists(schemaName: string): Promise<void> {
throw new Error('Unable to create schema, Druid does not support it');
}
public async getTablesQuery(schemaName: string) {
return this.query<TableQueryResult>('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ?', [
schemaName
]);
}
public async downloadQueryResults(query: string, values: unknown[], _options: DownloadQueryResultsOptions): Promise<DownloadQueryResultsResult> {
const { rows, columns } = await this.client.query<any>(query, this.normalizeQueryValues(values));
if (!columns) {
throw new Error(
'You are using an old version of Druid. Unable to detect column types in readOnly mode.'
);
}
const types: TableStructure = [];
for (const [name, meta] of Object.entries(columns)) {
types.push({
name,
type: this.toGenericType(meta.sqlType.toLowerCase()),
});
}
return {
rows,
types,
};
}View on GitHub (pinned to 7d981676b3)
Solutions
- Upgrade Druid to 0.22+ so the SQL API returns column metadata headers.
- Run Cube in non-readOnly mode where types are obtained via information schema instead of downloadQueryResults.
- Check that no reverse proxy strips the x-druid-sql-* response headers.
Example fix
// before (cube.js)
driverFactory: () => new DruidDriver({ ...config, readOnly: true })
// after
// upgrade Druid >= 0.22, or disable readOnly
driverFactory: () => new DruidDriver({ ...config }) Defensive patterns
Strategy: validation
Validate before calling
// ensure Druid version supports SQL type headers
const version = process.env.DRUID_VERSION; // or fetched
if (version && semver.lt(version, '0.22.0')) {
throw new Error('readOnly/downloadQueryResults requires Druid >= 0.22');
} Type guard
function hasColumnMetadata(res) {
return Array.isArray(res?.columns) && res.columns.length > 0;
} Try / catch
try {
const res = await driver.downloadQueryResults(sql, values, {});
} catch (e) {
if (e.message.includes('old version of Druid')) {
console.error('Upgrade Druid >= 0.22 or disable readOnly mode');
} else throw e;
} Prevention
- Run Druid 0.22+ where the SQL API returns x-druid-sql headers
- Avoid readOnly mode on old Druid clusters
- Ensure proxies do not strip x-druid-sql-* headers
When it happens
Trigger: Calling driver.downloadQueryResults() (used by Cube's readOnly/pre-aggregation preview flow) against a Druid version whose SQL endpoint does not return column headers, so client.query() yields columns === null.
Common situations: Connecting Cube to Druid < 0.22; broker config disabling the SQL header; proxy stripping response headers so x-druid-sql-header-included is lost.
Related errors
- Please specify CUBEJS_DB_URL
- options.meta must be a function
- Driver's .streamQuery() method is not implemented yet.
- ${this.constructor} driver supports only rows upload
- Unable to describe table
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/ebf152fa4a49caaf.
Report an issue: GitHub.