{"record":{"id":"f4a0c0affd609066","repo":"cube-js/cube","slug":"invalid-cron-string-every-in-refreshkey-er","errorCode":null,"errorMessage":"Invalid cron string '${every}' in refreshKey (${err})","messagePattern":"Invalid cron string '(.+?)' in refreshKey \\((.+?)\\)","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-schema-compiler/src/adapter/BaseQuery.js","lineNumber":4873,"sourceCode":"    };\n\n    try {\n      const interval = cronParser.parseExpression(every, opt);\n      let dayOffset = interval.next().getTime();\n      const dayOffsetPrev = interval.prev().getTime();\n\n      // If the cron fires exactly at the epoch, use 0 as dayOffset\n      if (dayOffsetPrev === 0) {\n        dayOffset = 0;\n      }\n\n      return {\n        start: interval.next(),\n        end: interval.next(),\n        dayOffset: dayOffset / 1000, // Convert from ms to seconds\n      };\n    } catch (err) {\n      throw new UserError(`Invalid cron string '${every}' in refreshKey (${err})`);\n    }\n  }\n\n  calcIntervalForCronString(refreshKey) {\n    const every = refreshKey.every || '1 hour';\n\n    const { start, end, dayOffset } = this.parseCronSyntax(every);\n\n    const interval = (end.getTime() - start.getTime()) / 1000;\n\n    if (\n      !/^(\\*|\\d+)? ?(\\*|\\d+) (\\*|\\d+) \\* \\* (\\*|\\d+)$/g.test(every.replace(/ +/g, ' ').replace(/^ | $/g, ''))\n    ) {\n      throw new UserError(`Your cron string ('${every}') is correct, but we support only equal time intervals.`);\n    }\n\n    let utcOffset = 0;\n","sourceCodeStart":4855,"sourceCodeEnd":4891,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js#L4855-L4891","documentation":"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.","triggerScenarios":"refreshKey: { every: 'bad cron' } — a syntactically invalid cron expression (wrong field count, non-numeric tokens, out-of-range values) passed to refreshKey or everyRefreshKeySql.","commonSituations":"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.","solutions":["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'","Validate the cron locally with cron-parser before deploying","If a fixed interval was intended, use the '<n> <unit>' form (e.g. '1 hour') instead of cron"],"exampleFix":"// before\nrefreshKey: { every: 'every 2 hours' }\n// after\nrefreshKey: { every: '0 */2 * * *' }","handlingStrategy":"validation","validationCode":"const cronParser = require('cron-parser');\nfunction validateCron(every) {\n  if (/^\\d+ (second|minute|hour|day|week|month|quarter|year)s?$/.test(every)) return;\n  try { cronParser.parseExpression(every); } catch (e) { throw new Error(`Invalid cron '${every}': ${e.message}`); }\n}","typeGuard":"const isCronString = (s) => typeof s === 'string' && s.trim().split(/\\s+/).length === 5;","tryCatchPattern":"try { await cubeApi.query(q); } catch (e) { if (/Invalid cron string/.test(e.message)) console.error('Fix refreshKey.every:', e.message); throw e; }","preventionTips":["Test cron strings with cron-parser before deploying models","Prefer simple 'n unit' intervals over cron when possible","Keep cron expressions to standard 5-field syntax"],"tags":["refresh-key","cron","user-error"],"backgroundTag":"invalid-cron-expression","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}