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
- Add time: { sql: `${CUBE}.timestamp` } (or your event time column) to the funnel definition
- Confirm the property is named `time`, not `timestamp` or `date`
- 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
- Include time: { sql: ... } in every funnel definition
- Validate the whole funnel object before calling eventFunnel
- Name the field exactly `time` — not timestamp or date
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
- userId.sql is not defined
- steps are 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/a513f1fc25a9bf1c.
Report an issue: GitHub.