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
- Provide at least two step definitions: steps: [{ event: 'signup' }, { event: 'purchase' }]
- Ensure steps is a YAML sequence (each step prefixed with '- ') in YAML schemas
- 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
- Never pass an empty steps array — build funnels only when steps exist
- In YAML, ensure each step is a '- ' list item
- Guard dynamically generated step lists before calling eventFunnel
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
- userId.sql is not defined
- time.sql is not defined
- Invalid query format: ${error.message || error.toString()}
- Subquery measure ${m.expressionName} should reference at lea
- List of references and a function are expected in form: dynR
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/ab217622f9708d83.
Report an issue: GitHub.