cube-js/cube · error · UserError
Hierarchical time shift is not supported but was provided fo
Error message
Hierarchical time shift is not supported but was provided for '${memPath}'. Parent time shift is '${symbol.shiftInterval}' and current is '${this.safeEvaluateSymbolContext().timeShifts?.[memPath]}' What it means
Cube propagates time shifts hierarchically when evaluating time symbols: a parent's shift is applied to child members. Applying another shift inside an already-shifted member is ambiguous/unsupported, so Cube throws this UserError when both a hierarchical shift (timeShifts[memPath] or commonTimeShift) and the symbol's own shiftInterval are present.
Source
Thrown at packages/cubejs-schema-compiler/src/adapter/BaseQuery.js:3541
const td = this.newTimeDimension({
dimension: this.cubeEvaluator.pathFromArray([cubeName, name]),
granularity: subPropertyName
});
// for time dimension with granularity convertedToTz() is called internally in dimensionSql() flow,
// so we need to ignore convertTz later even if context convertTzForRawTimeDimension is set to true
return this.evaluateSymbolSqlWithContext(
() => td.dimensionSql(),
{ ignoreConvertTzForTimeDimension: true },
);
} else {
let res = this.autoPrefixAndEvaluateSql(cubeName, symbol.sql, isMemberExpr);
const memPath = this.cubeEvaluator.pathFromArray([cubeName, name]);
// Skip view's member evaluation as there will be underlying cube's same member evaluation
if (symbol.type === 'time' && !this.cubeEvaluator.cubeFromPath(memPath).isView) {
if (this.safeEvaluateSymbolContext().timeShifts?.[memPath]) {
if (symbol.shiftInterval) {
throw new UserError(`Hierarchical time shift is not supported but was provided for '${memPath}'. Parent time shift is '${symbol.shiftInterval}' and current is '${this.safeEvaluateSymbolContext().timeShifts?.[memPath]}'`);
}
res = `(${this.addTimestampInterval(res, this.safeEvaluateSymbolContext().timeShifts?.[memPath])})`;
} else if (this.safeEvaluateSymbolContext().commonTimeShift) {
if (symbol.shiftInterval) {
throw new UserError(`Hierarchical time shift is not supported but was provided for '${memPath}'. Parent time shift is '${symbol.shiftInterval}' and current is '${this.safeEvaluateSymbolContext().commonTimeShift}'`);
}
res = `(${this.addTimestampInterval(res, this.safeEvaluateSymbolContext().commonTimeShift)})`;
}
}
if (this.safeEvaluateSymbolContext().convertTzForRawTimeDimension &&
!this.safeEvaluateSymbolContext().ignoreConvertTzForTimeDimension &&
!memberExpressionType &&
symbol.type === 'time' &&
this.cubeEvaluator.byPathAnyType(memberPathArray).ownedByCube
) {
res = this.convertTz(res);
}View on GitHub (pinned to 7d981676b3)
Solutions
- Remove the shiftInterval from the member definition OR remove the query-level/commonTimeShift for that dimension — apply only one shift.
- Apply the combined shift manually: compute the net interval and pass a single timeShift.
- If the member lives in a view, ensure the shift is applied at one level only (view OR cube), not both.
- Catch UserError and surface guidance that hierarchical (stacked) time shifts are unsupported.
Example fix
// before (schema shift + query shift collide)
shiftInterval: '-1 month' // in dimension definition
// and query: timeShifts: { 'Orders.createdAt': '-1 month' }
// after (single shift)
// remove schema shiftInterval, keep only:
query.timeShifts = { 'Orders.createdAt': '-2 month' } // combine intervals manually Defensive patterns
Strategy: validation
Validate before calling
// Ensure a member is shifted at most once (schema OR query), never both
function assertSingleShift(dimensionDef, queryTimeShifts, memberPath) {
const schemaShift = Boolean(dimensionDef && dimensionDef.shiftInterval);
const queryShift = Boolean(queryTimeShifts && queryTimeShifts[memberPath]);
if (schemaShift && queryShift) {
throw new Error(`Member ${memberPath} is shifted both in schema and query; remove one`);
}
} Type guard
const hasNoStackedShift = (symbol, ctx, memPath) => !((ctx.timeShifts?.[memPath] || ctx.commonTimeShift) && symbol.shiftInterval);
Try / catch
try {
return await cubeApi.load(query);
} catch (e) {
if (/Hierarchical time shift is not supported/.test(e.message)) {
console.error('Apply the time shift at one level only (schema or query)');
}
throw e;
} Prevention
- Apply time shifts in exactly one place: schema definition or query parameter
- Combine multiple shifts into a single net interval manually before querying
- Document view-level shifts so teams don't add a second shift at query time
When it happens
Trigger: A time dimension (non-view) is evaluated with a timeShift in the evaluation context (or a commonTimeShift), and the same member's symbol also defines its own shiftInterval — e.g. shifting a shifted dimension, or a query-level timeShift applied to a dimension that already has a shiftInterval in its definition.
Common situations: Applying query-level timeShifts (dateRange shift API) on top of schema-defined shifted dimensions; nested shifted views; rolling window definitions combined with per-query time shift parameters.
Related errors
- compareDateRange can only exist for one timeDimension
- Can't find common parent for '${granularityA}' and '${granul
- Time series queries without dateRange aren't supported
- Can't build query for time dimensions with different date ra
- Hierarchical time shift is not supported but was provided fo
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/b1b552804efc3702.
Report an issue: GitHub.