cube-js/cube · error · Error

steps are not defined

Error message

steps are not defined

What it means

The Funnels schema extension requires funnel definitions to include a steps array defining the funnel sequence; the error fires in eventFunnel when steps is absent or empty. Like the other funnel guards it is a plain schema validation check in the extension, so the fix belongs in the data model, not in query parameters.

Source

Thrown at packages/cubejs-schema-compiler/src/extensions/Funnels.ts:17

import inflection from 'inflection';
import { AbstractExtension } from './extension.abstract';

export class Funnels extends AbstractExtension {
  // TODO check timeToConvert is absent on first step
  // TODO name can be a title
  public eventFunnel(funnelDefinition) {
    if (!funnelDefinition.userId || !funnelDefinition.userId.sql) {
      throw new Error('userId.sql is not defined'); // TODO schema check
    }

    if (!funnelDefinition.time || !funnelDefinition.time.sql) {
      throw new Error('time.sql is not defined'); // TODO schema check
    }

    if (!funnelDefinition.steps || !funnelDefinition.steps.length) {
      throw new Error('steps are not defined'); // TODO schema check
    }

    return this.cubeFactory({
      sql: () => {
        const eventJoin =
          funnelDefinition.steps.map((s, i) => this.eventCubeJoin(funnelDefinition, s, funnelDefinition.steps[i - 1]));
        const userIdColumnsAndTime =
          funnelDefinition.steps.map(s => `${this.eventsTableName(s)}.user_id ${this.stepUserIdColumnName(s)}`)
            .concat([`${this.eventsTableName(funnelDefinition.steps[0])}.t`]).join(',\n');
        return `WITH joined_events AS (
    select
    ${userIdColumnsAndTime}
    FROM
${eventJoin.join('\nLEFT JOIN\n')}
  )
  select user_id, first_step_user_id, step, max(t) t from (
    ${funnelDefinition.steps.map(s => this.stepSegmentSelect(funnelDefinition, s)).join('\nUNION ALL\n')}
  ) as event_steps GROUP BY 1, 2, 3`;

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Provide at least two step definitions: steps: [{ event: 'signup' }, { event: 'purchase' }]
  2. Ensure steps is a YAML sequence (each step prefixed with '- ') in YAML schemas
  3. Guard dynamic step generation so empty arrays never reach eventFunnel

Example fix

// before
eventFunnel({
  userId: { sql: `${CUBE}.user_id` },
  time: { sql: `${CUBE}.timestamp` },
  steps: []
});
// after
eventFunnel({
  userId: { sql: `${CUBE}.user_id` },
  time: { sql: `${CUBE}.timestamp` },
  steps: [
    { event: 'signup' },
    { event: 'purchase' }
  ]
});
Defensive patterns

Strategy: validation

Validate before calling

const hasSteps = (f) => Array.isArray(f?.steps) && f.steps.length > 0;

Type guard

const hasSteps = (f) => Array.isArray(f?.steps) && f.steps.length >= 1 && f.steps.every(s => s && typeof s === 'object');

Try / catch

try {
  funnelCube.eventFunnel(def);
} catch (e) {
  if (e.message === 'steps are not defined') {
    console.error('Provide a non-empty steps array in the funnel definition');
  }
  throw e;
}

Prevention

When it happens

Trigger: eventFunnel called with steps undefined, steps: [], or steps set to a non-array value.

Common situations: Defining a funnel placeholder before filling in steps; YAML indentation flattening the steps list; filtering logic accidentally producing an empty steps array.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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