cube-js/cube · error · Error
Mixed offset rolling window querying is not supported
Error message
Mixed offset rolling window querying is not supported
What it means
When computing the maximum rolling window of two windows, if one window has offset 'start' (leading from start) and the other 'end' (or unset), no single combined window can represent both, so maxRollingWindow throws. The TODO notes a virtual 'both' offset would be needed.
Source
Thrown at packages/cubejs-schema-compiler/src/adapter/CubeStoreQuery.ts:295
trailing = a.trailing;
} else {
trailing = this.parseSecondDuration(a.trailing) > this.parseSecondDuration(b.trailing) ? a.trailing : b.trailing;
}
let leading;
if (a.leading === 'unbounded' || b.leading === 'unbounded') {
leading = 'unbounded';
} else if (!a.leading) {
leading = b.leading;
} else if (!b.leading) {
leading = a.leading;
} else {
leading = this.parseSecondDuration(a.leading) > this.parseSecondDuration(b.leading) ? a.leading : b.leading;
}
if ((a.offset || 'end') !== (b.offset || 'end')) {
// TODO introduce virtual 'both' offset and return it if max receives 'start' and 'end'
throw new Error('Mixed offset rolling window querying is not supported');
}
return {
trailing,
leading,
offset: a.offset
};
}
public overTimeSeriesForSelectRollup(cumulativeMeasures, otherMeasures, timeDimension, preAggregationForQuery) {
const rollupMeasures = this.preAggregations.rollupMeasures(preAggregationForQuery);
const renderedReference = rollupMeasures.map(measure => {
const m = this.newMeasure(measure);
const renderSql = () => {
if (timeDimension && m.isCumulative()) {
const measureSql = m.cumulativeMeasureSql();
const rollingWindow = m.rollingWindowDefinition();
const preceding = rollingWindow.trailing ? `${this.toInterval(rollingWindow.trailing)} PRECEDING` : '';View on GitHub (pinned to 7d981676b3)
Solutions
- Make all rolling windows in the query use the same offset (all 'start' or all 'end').
- Split into two separate queries, one per offset type.
- Remove the explicit offset from one window so both default to 'end'.
Example fix
// before
rollingWindow: { trailing: '2 day', offset: 'start' } // in one measure
rollingWindow: { trailing: '7 day' } // in another -> defaults to 'end'
// after
rollingWindow: { trailing: '2 day', offset: 'end' }
rollingWindow: { trailing: '7 day', offset: 'end' } Defensive patterns
Strategy: validation
Validate before calling
const offsets = measures.map(m => m.rollingWindow?.offset || 'end');
if (new Set(offsets).size > 1) throw new Error('All rolling windows must share the same offset'); Try / catch
try { await cube.load(q) } catch (e) { if (/Mixed offset rolling window/.test(e.message)) { /* split query per offset */ } else throw e; } Prevention
- Standardize offset ('start' vs 'end') across rolling windows in a project
- Split comparisons of MTD vs trailing windows into separate queries
- Code-review rollingWindow configs for offset consistency
When it happens
Trigger: A query (or merged query with multiple rolling windows on the same cube) mixes windows like `{ trailing: '2 day', offset: 'start' }` and `{ trailing: '2 day', offset: 'end' }`.
Common situations: Comparing current-period-to-date (offset: 'start') with trailing complete windows (offset: 'end') in the same query; orchestrator merging two queried rolling windows into one pre-aggregation window.
Related errors
- Cannot transform interval expression "${interval}" to CubeSt
- Unsupported table data passed to ${this.constructor}
- Unable to import (as rows) in Cube Store: empty columns. Mos
- Unable to import (as csv) in Cube Store: empty columns. Most
- Unable to import (as stream) in Cube Store: empty columns. M
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/d08dea9f9ce3365b.
Report an issue: GitHub.