cube-js/cube · error · UserError
Data blending query without granularity is not supported
Error message
Data blending query without granularity is not supported
What it means
A data blending query must include at least one time granularity so the sub-queries have a common axis to blend on. When getQueryGranularity returns an empty list — meaning none of the blended sub-queries has a granularity on its timeDimensions — the gateway throws this UserError instead of producing an ambiguous blend.
Source
Thrown at packages/cubejs-api-gateway/src/gateway.ts:1516
normalizedQueries: normalizedQueries.map(q => this.sanitizeQueryForLogging(q)),
duration: Date.now() - startTime,
query
}, context);
normalizedQueries = normalizedQueries.map(q => remapToQueryAdapterFormat(q));
if (normalizedQueries.some((currentQuery) => !currentQuery)) {
throw new Error('queryTransformer returned null query. Please check your queryTransformer implementation');
}
if (queryType === QueryTypeEnum.BLENDING_QUERY) {
const queryGranularity = getQueryGranularity(normalizedQueries);
if (queryGranularity.length > 1) {
throw new UserError('Data blending query granularities must match');
}
if (queryGranularity.length === 0) {
throw new UserError('Data blending query without granularity is not supported');
}
}
return [queryType, normalizedQueries, queryNormalizationResult.map((it) => remapToQueryAdapterFormat(it.normalizedQuery))];
}
protected async sql4sql({
query,
disablePostProcessing,
context,
res,
}: {query: string, disablePostProcessing: boolean} & BaseRequest) {
try {
await this.assertApiScope('sql', context.securityContext);
const result = await this.sqlServer.sql4sql(query, disablePostProcessing, context.securityContext);
await res({ sql: result });View on GitHub (pinned to 7d981676b3)
Solutions
- Add `granularity` (e.g. 'day' or 'month') to the timeDimension of each sub-query in the blended array.
- Ensure the blend actually needs blending: if no time axis is required, send a single query with combined measures instead.
- In dashboards, require the date-granularity picker to have a selection before issuing a blend request.
Example fix
// before
[{ measures:['a.c'], timeDimensions:[{dimension:'a.date', dateRange:['2024-01-01','2024-01-31']}] },
{ measures:['b.c'], timeDimensions:[{dimension:'b.date', dateRange:['2024-01-01','2024-01-31']}] }]
// after
[{ measures:['a.c'], timeDimensions:[{dimension:'a.date', granularity:'day', dateRange:['2024-01-01','2024-01-31']}] },
{ measures:['b.c'], timeDimensions:[{dimension:'b.date', granularity:'day', dateRange:['2024-01-01','2024-01-31']}] }] Defensive patterns
Strategy: validation
Validate before calling
function blendHasGranularity(queries) {
return queries.some(q => (q.timeDimensions ?? []).some(td => td.granularity));
}
if (Array.isArray(query) && !blendHasGranularity(query)) throw new Error('Blended queries require a time granularity'); Type guard
function hasAnyGranularity(qs: any[]): boolean {
return qs.some(q => (q.timeDimensions ?? []).some(td => typeof td.granularity === 'string' && td.granularity.length > 0));
} Try / catch
try {
return await cubeApi.load(queries);
} catch (e) {
if (String(e?.message).includes('without granularity')) {
return await cubeApi.load(queries.map(q => ({ ...q, timeDimensions: withDefaultGranularity(q.timeDimensions) })));
}
throw e;
} Prevention
- Always attach a default granularity (e.g. 'day') when building blended queries.
- Disable blend submission in UIs until a date granularity is selected.
- If no time axis is needed, collapse the blend into a single query.
When it happens
Trigger: POST /cubejs-api/v1/load with an array query where every sub-query's timeDimensions omit `granularity` (or no timeDimensions at all), while queryType resolves to BLENDING_QUERY.
Common situations: Users deselecting the date grouping in a dashboard builder while still requesting multiple datasets as a blend; constructing blended queries from raw JSON without a granularity field; assuming blending works with only filters/dateRanges.
Related errors
- Data blending query granularities must match
- Can't find common parent for '${granularityA}' and '${granul
- maskedMembers cannot be provided in the query
- '${queryType}' query type is not supported by the client.Ple
- Unsupported time granularity: ${granularity}
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/24efa6fc7d1fbd25.
Report an issue: GitHub.