{"record":{"id":"521a6727e726fed9","repo":"n8n-io/n8n","slug":"interval-intervalseconds-must-be-a-positive-intege","errorCode":null,"errorMessage":"interval.intervalSeconds must be a positive integer, got ${JSON.stringify(schedule.intervalSeconds)}","messagePattern":"interval\\.intervalSeconds must be a positive integer, got (.+?)","errorType":"validation","errorClass":"InvalidScheduleError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/scheduler/src/core/recurrence/kinds/interval.ts","lineNumber":14,"sourceCode":"import { Time } from '@n8n/constants';\n\nimport { InvalidScheduleError } from '../../errors';\nimport type { IntervalSchedule, ScheduledJob } from '../../types';\nimport { required } from '../field';\n\n/**\n * Checks that an interval schedule has a positive whole number of seconds.\n * @param schedule The interval schedule to check.\n * @throws {InvalidScheduleError} When the interval is not a positive integer.\n */\nexport function validateInterval(schedule: IntervalSchedule): void {\n\tif (!Number.isInteger(schedule.intervalSeconds) || schedule.intervalSeconds <= 0) {\n\t\tthrow new InvalidScheduleError(\n\t\t\t`interval.intervalSeconds must be a positive integer, got ${JSON.stringify(schedule.intervalSeconds)}`,\n\t\t);\n\t}\n}\n\n/**\n * The next interval fire after `after`: `after` plus the interval. Counts real\n * elapsed time, so daylight-saving changes never shift a fire.\n * @param schedule The interval schedule.\n * @param after The previous occurrence.\n * @returns The next fire time.\n */\nexport function intervalNextRun(schedule: IntervalSchedule, after: Date): Date {\n\treturn new Date(after.getTime() + schedule.intervalSeconds * Time.seconds.toMilliseconds);\n}\n\n/**\n * Every interval fire starting at `first`, oldest first.","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/scheduler/src/core/recurrence/kinds/interval.ts#L1-L32","documentation":"Thrown by validateInterval when schedule.intervalSeconds is not an integer, or is <= 0. Intervals count whole seconds between fires; a fractional second is not representable, and a non-positive interval would either never fire or hot-loop.","triggerScenarios":"An interval schedule with intervalSeconds: 0, -5, 1.5, NaN, or Infinity. Number.isInteger(intervalSeconds) && intervalSeconds > 0 must hold.","commonSituations":"User enters 0.5 seconds intending 500ms (sub-second intervals are not supported - use cron or a different mechanism); a config that left intervalSeconds unset and defaulted to 0; a float from a unit conversion (minutes -> seconds with rounding); NaN from parseFloat on a non-numeric env var.","solutions":["Set intervalSeconds to a positive integer (e.g. 60 for one minute).","For sub-second scheduling, use a different mechanism - the interval scheduler only supports whole seconds.","Round before passing: Math.max(1, Math.round(seconds)).","Validate with Number.isInteger in your config loader."],"exampleFix":"// before\nvalidateInterval({ kind: 'interval', intervalSeconds: 0.5 }); // throws - not an integer\n\n// after - coerce to a positive whole second\nconst intervalSeconds = Math.max(1, Math.round(Number(userInput) || 60));\nvalidateInterval({ kind: 'interval', intervalSeconds });","handlingStrategy":"validation","validationCode":"function normalizeIntervalSeconds(raw: unknown): number {\n  const n = Math.floor(Number(raw));\n  if (!Number.isInteger(n) || n <= 0) {\n    throw new Error('intervalSeconds must be a positive integer (sub-second scheduling is not supported)');\n  }\n  return n;\n}","typeGuard":"function isPositiveIntegerSeconds(v: unknown): v is number {\n  return typeof v === 'number' && Number.isInteger(v) && v > 0;\n}","tryCatchPattern":null,"preventionTips":["Round before passing: Math.max(1, Math.round(Number(raw))).","For sub-second scheduling, use a different mechanism - the interval scheduler only supports whole seconds.","Reject fractional and zero values in the UI with a clear message about whole seconds.","Unit-test the config loader with 0, 0.5, NaN, undefined."],"tags":["scheduler","interval","validation","numeric"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}