cube-js/cube · error · Error
${granularity} granularity is not supported
Error message
${granularity} granularity is not supported What it means
QuestQuery.timeGroupedColumn builds the SQL for a time-dimension granularity grouping using the GRANULARITY_TO_INTERVAL map. If the requested granularity string is not a key of that map, the interval is undefined and the driver throws rather than emitting invalid SQL.
Source
Thrown at packages/cubejs-questdb-driver/src/QuestQuery.ts:116
return `dateadd('${unit}', ${-number * factor}, ${date})`;
}
public addInterval(date: string, interval: string): string {
const [number, type] = this.parseInterval(interval);
const { unit, factor } = INTERVAL_TO_QUEST_DATE_UNIT[type];
return `dateadd('${unit}', ${number * factor}, ${date})`;
}
public unixTimestampSql(): string {
// QuestDB's now() function returns epoch timestamp with microsecond granularity.
return 'now() / 1000000';
}
public timeGroupedColumn(granularity: string, dimension: string): string {
const interval = GRANULARITY_TO_INTERVAL[granularity];
if (interval === undefined) {
throw new Error(`${granularity} granularity is not supported`);
}
return `timestamp_floor('${GRANULARITY_TO_INTERVAL[granularity]}', ${dimension})`;
}
public dateBin(interval: string, source: string, origin: string): string {
const { stride, unit, count } = this.questFloorStride(interval);
// timestamp_floor(stride, ts, origin) only buckets forward from `origin`, so
// an origin later than the data collapses every row into a single bucket.
// Shift `origin` back by a whole number of strides (which preserves the bin
// phase, as flooring is periodic modulo the stride) to just before a fixed
// anchor that precedes any realistic data.
const shift = this.dateBinOriginShift(origin, unit, count);
const shiftedOrigin = shift > 0
? `dateadd('${unit}', ${-shift}, cast('${origin}' as timestamp))`
: `cast('${origin}' as timestamp)`;
return `timestamp_floor('${stride}', ${source}, ${shiftedOrigin})`;
}View on GitHub (pinned to 7d981676b3)
Solutions
- Use only granularities supported by the driver (second, minute, hour, day, week, month, quarter, year — check GRANULARITY_TO_INTERVAL in QuestQuery.ts)
- Upgrade cubejs-questdb-driver if the needed granularity was added in a newer release
- Pre-aggregate/roll up data in the cube schema instead of relying on an unsupported native granularity
Example fix
// before
{ dimension: 'Events.timestamp', granularity: 'fortnight' }
// after
{ dimension: 'Events.timestamp', granularity: 'week' } Defensive patterns
Strategy: validation
Validate before calling
const supported = ['second','minute','hour','day','week','month','quarter','year']; if (!supported.includes(granularity)) throw new Error(`Unsupported granularity ${granularity} for QuestDB`); Type guard
function isQuestGranularity(g) { return g in GRANULARITY_TO_INTERVAL; } Try / catch
try { await cube.query(...); } catch (e) { if (e.message.includes('granularity is not supported')) { /* fall back to 'day' or upgrade driver */ } throw e; } Prevention
- Restrict timeGranularities in cube configs to driver-supported values
- Keep the questdb driver current for added granularities
- Test compiled SQL per granularity in CI
When it happens
Trigger: Compiling a query with a time dimension granularity not supported by the QuestDB driver — e.g. custom granularities passed as arbitrary strings, or granularity names the driver's map lacks.
Common situations: Using cube's custom granularity strings (like 'quarter' in older versions or custom intervals) against a driver version whose GRANULARITY_TO_INTERVAL map does not define them; typos in granularity configuration.
Related errors
- Data blending query granularities must match
- Data blending query without granularity is not supported
- Unsupported time granularity: ${granularity}
- Cannot transform interval expression "${interval}" to Databr
- Unable to detect type for field "${f.name}" with dataTypeID:
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/5ebcdc18aea9a93b.
Report an issue: GitHub.