cube-js/cube · error · UserError

You cannot use dimension and measure in same condition: ${JS

Error message

You cannot use dimension and measure in same condition: ${JSON.stringify(f)}

What it means

When compiling the filter tree, Cube classifies each leaf as filtering either a dimension or a measure. A single condition referencing both a dimension and a measure is ambiguous for SQL generation (it mixes row-level and aggregate-level predicates), so the library rejects it with this UserError.

Source

Thrown at packages/cubejs-schema-compiler/src/adapter/BaseQuery.js:228

            dimensionGroup: true,
            measure: null,
          };
        }
        if (!dimension.length && measure.length) {
          return {
            values: this.extractFiltersAsTree(f[operator]),
            operator,
            dimension: null,
            measureGroup: true,
          };
        }
        if (!dimension.length && !measure.length) {
          return {
            values: [],
            operator,
          };
        }
        throw new UserError(`You cannot use dimension and measure in same condition: ${JSON.stringify(f)}`);
      }

      if (!f.member && !f.dimension) {
        throw new UserError(`member attribute is required for filter ${JSON.stringify(f)}`);
      }

      if (this.cubeEvaluator.isMeasure(f.member || f.dimension)) {
        return Object.assign({}, f, {
          dimension: null,
          measure: f.member || f.dimension
        });
      }

      return Object.assign({}, f, {
        measure: null,
        dimension: f.member || f.dimension
      });
    });

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Split the condition: dimension filters and measure filters must be separate filter nodes
  2. Put measure conditions in the 'filters' acting on measures or in having-style position, not mixed in one leaf
  3. Check filter-building code that merges member lists into a single object

Example fix

// before
{ member: ['Orders.status', 'Orders.count'], operator: 'equals', values: ['shipped', 10] }
// after
filters: [
  { member: 'Orders.status', operator: 'equals', values: ['shipped'] },
  { member: 'Orders.count', operator: 'equals', values: [10] }
]
Defensive patterns

Strategy: validation

Validate before calling

// split mixed leaves before sending
function splitMixedFilters(filters, isMeasure) {
  return filters.flatMap(f => {
    const members = [].concat(f.member || f.dimension || []);
    if (members.some(isMeasure) && members.some(m => !isMeasure(m))) {
      return members.map(m => ({ ...f, member: m }));
    }
    return [f];
  });
}
query.filters = splitMixedFilters(query.filters, isKnownMeasure);

Type guard

const isPureDimOrMeasure = (f, isMeasure) => {
  const ms = [].concat(f.member || f.dimension || []);
  const hasDim = ms.some(m => !isMeasure(m));
  const hasMea = ms.some(isMeasure);
  return !(hasDim && hasMea);
};

Try / catch

try {
  await cubeApi.load(query);
} catch (e) {
  if (/dimension and measure in same condition/.test(e.message)) {
    // split the filter into separate conditions and retry once
  } else throw e;
}

Prevention

When it happens

Trigger: A leaf filter whose resolved members include at least one dimension and at least one measure simultaneously (e.g. f.dimension plus a measure member, or an 'or'/'and' leaf mixing them via member arrays), with an operator that produced non-empty lists for both.

Common situations: Building combined filter UIs where users can pick both attributes and metrics in one condition; programmatic filter merging that concatenates dimension and measure members into one node.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/b74c55dbf97c204e. Report an issue: GitHub.