cube-js/cube · error · UserError

Invalid cron string '${every}' in refreshKey (${err})

Error message

Invalid cron string '${every}' in refreshKey (${err})

What it means

When a refreshKey uses a cron expression (`every: '<cron>'`), BaseQuery computes the interval by evaluating the next occurrences with cron-parser. If the string cannot be parsed, the underlying parser error is wrapped in this UserError.

Source

Thrown at packages/cubejs-schema-compiler/src/adapter/BaseQuery.js:4873

    };

    try {
      const interval = cronParser.parseExpression(every, opt);
      let dayOffset = interval.next().getTime();
      const dayOffsetPrev = interval.prev().getTime();

      // If the cron fires exactly at the epoch, use 0 as dayOffset
      if (dayOffsetPrev === 0) {
        dayOffset = 0;
      }

      return {
        start: interval.next(),
        end: interval.next(),
        dayOffset: dayOffset / 1000, // Convert from ms to seconds
      };
    } catch (err) {
      throw new UserError(`Invalid cron string '${every}' in refreshKey (${err})`);
    }
  }

  calcIntervalForCronString(refreshKey) {
    const every = refreshKey.every || '1 hour';

    const { start, end, dayOffset } = this.parseCronSyntax(every);

    const interval = (end.getTime() - start.getTime()) / 1000;

    if (
      !/^(\*|\d+)? ?(\*|\d+) (\*|\d+) \* \* (\*|\d+)$/g.test(every.replace(/ +/g, ' ').replace(/^ | $/g, ''))
    ) {
      throw new UserError(`Your cron string ('${every}') is correct, but we support only equal time intervals.`);
    }

    let utcOffset = 0;

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Fix the cron string syntax — it must be a valid cron expression (e.g. '0 */2 * * *' for every 2 hours) or a simple interval like '1 hour'
  2. Validate the cron locally with cron-parser before deploying
  3. If a fixed interval was intended, use the '<n> <unit>' form (e.g. '1 hour') instead of cron

Example fix

// before
refreshKey: { every: 'every 2 hours' }
// after
refreshKey: { every: '0 */2 * * *' }
Defensive patterns

Strategy: validation

Validate before calling

const cronParser = require('cron-parser');
function validateCron(every) {
  if (/^\d+ (second|minute|hour|day|week|month|quarter|year)s?$/.test(every)) return;
  try { cronParser.parseExpression(every); } catch (e) { throw new Error(`Invalid cron '${every}': ${e.message}`); }
}

Type guard

const isCronString = (s) => typeof s === 'string' && s.trim().split(/\s+/).length === 5;

Try / catch

try { await cubeApi.query(q); } catch (e) { if (/Invalid cron string/.test(e.message)) console.error('Fix refreshKey.every:', e.message); throw e; }

Prevention

When it happens

Trigger: refreshKey: { every: 'bad cron' } — a syntactically invalid cron expression (wrong field count, non-numeric tokens, out-of-range values) passed to refreshKey or everyRefreshKeySql.

Common situations: Hand-writing cron strings with mistakes (e.g. '0 */6 * *' missing a field); using natural language like 'every hour' instead of cron syntax; locale-dependent separators; copying 5-field cron into a parser expecting different format.

Related errors


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