cube-js/cube · error · Error

Pre-aggregation definition is malformed

Error message

Pre-aggregation definition is malformed

What it means

CubePreAggregationConverter.convertJS parses a pre-aggregation definition snippet with Babel and expects the first statement to be an object expression ({ ... }). If the parsed code is not an object expression (or fails that shape check), a plain Error 'Pre-aggregation definition is malformed' is thrown during AST-based pre-aggregation conversion.

Source

Thrown at packages/cubejs-schema-compiler/src/compiler/converters/CubePreAggregationConverter.ts:46

  }

  protected convertJS(cubeDefSet: JsSet) {
    const { preAggregationName, code } = this.preAggregationDefinition;
    const { cubeDefinition } = cubeDefSet;

    let preAggregationNode: t.ObjectExpression | null = null;
    const preAggregationAst = parse(`(${code})`);

    if (t.isExpressionStatement(preAggregationAst.program.body[0])) {
      const [statement] = preAggregationAst.program.body;

      if (t.isObjectExpression(statement.expression)) {
        preAggregationNode = statement.expression;
      }
    }

    if (preAggregationNode === null) {
      throw new Error('Pre-aggregation definition is malformed');
    }

    let anchor: t.ObjectExpression | null = null;

    cubeDefinition.properties.forEach((prop) => {
      if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
        if (prop.key.name === 'preAggregations' && t.isObjectExpression(prop.value)) {
          anchor = prop.value;

          prop.value.properties.forEach((p) => {
            if (t.isObjectProperty(p) && t.isIdentifier(p.key)) {
              if (p.key.name === preAggregationName) {
                throw new UserError(`Pre-aggregation '${preAggregationName}' is already defined`);
              }
            }
          });
        }
      }

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Ensure the pre-aggregation code is a complete object literal, e.g. { measures: [...], timeDimension: ..., granularity: 'day' }
  2. Log/inspect the code string passed to the converter before conversion
  3. Wrap non-expression snippets in parentheses/braces so Babel parses them as ObjectExpression
  4. Catch and report this Error upstream since it is a plain Error, not UserError

Example fix

// before
const code = "rollups => rollups.main()";

// after
const code = "{ measures: [orders.count], timeDimension: orders.createdAt, granularity: 'day' }";
Defensive patterns

Strategy: validation

Validate before calling

const { parse } = require('@babel/parser');
const t = require('@babel/types');
function isObjectLiteralDefinition(code) {
  const ast = parse(`(${code})`);
  const [stmt] = ast.program.body;
  return t.isExpressionStatement(stmt) && t.isObjectExpression(stmt.expression);
}

Try / catch

try {
  converter.convert(astByCubeName);
} catch (e) {
  if (e.message === 'Pre-aggregation definition is malformed') {
    console.error('Pre-aggregation code must be an object literal');
  }
}

Prevention

When it happens

Trigger: Submitting a preAggregations definition whose code parses to something other than an object literal — e.g. a function call, identifier, array, or empty snippet — via the schema converter API or playground pre-aggregation flows.

Common situations: Programmatic pre-aggregation creation where the code string was truncated or built incorrectly, IDE copy/paste dropping the braces, or passing a function-style definition where an object is required.

Understand the failure class

Related errors


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