cube-js/cube · error · Error

time.sql is not defined

Error message

time.sql is not defined

What it means

The Funnels schema extension requires every funnel definition to declare time.sql, which provides the event timestamp used to order funnel steps. The error fires in eventFunnel when the time property is missing or has no sql — it is a plain schema validation guard (marked TODO for a proper schema check), not a runtime query failure.

Source

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

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')}

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Add time: { sql: `${CUBE}.timestamp` } (or your event time column) to the funnel definition
  2. Confirm the property is named `time`, not `timestamp` or `date`
  3. Ensure the sql value resolves against the event cube's columns

Example fix

// before
eventFunnel({
  userId: { sql: `${CUBE}.user_id` },
  time: 'events.ts'
});
// after
eventFunnel({
  userId: { sql: `${CUBE}.user_id` },
  time: { sql: `${CUBE}.timestamp` }
});
Defensive patterns

Strategy: validation

Validate before calling

const hasTimeSql = (f) => !!f && !!f.time && typeof f.time.sql !== 'undefined';

Type guard

const hasTimeSql = (f) => typeof f?.time?.sql === 'string' || typeof f?.time?.sql === 'function';

Try / catch

try {
  funnelCube.eventFunnel(def);
} catch (e) {
  if (e.message === 'time.sql is not defined') {
    console.error('Add time: { sql: `${CUBE}.timestamp` } to the funnel definition');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling eventFunnel with funnelDefinition.time undefined or not containing a sql property (e.g. a plain string or an empty object).

Common situations: Funnel definitions copied from old examples; forgetting to add the timestamp field; passing a member reference as a string instead of `{ sql: ... }`.

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/a513f1fc25a9bf1c. Report an issue: GitHub.