denoland/deno · error · TypeError

Invalid cron schedule: start=${start}, end=${end}, every=${e

Error message

Invalid cron schedule: start=${start}, end=${end}, every=${every}

What it means

Deno.CronSchedule field objects are converted by formatToCronSchedule. Valid shapes: {exact: n}, {exact: [...]}, {every} alone, {start}, {start, every}, {start, end}, {start, end, every}. A field with end but no start (with or without every) has no cron representation and throws.

Source

Thrown at ext/cron/01_cron.ts:53

    const { exact } = value as { exact: number | number[] };
    if (exact === undefined) {
      const { start, end, every } = value as {
        start?: number;
        end?: number;
        every?: number;
      };
      if (start !== undefined && end !== undefined && every !== undefined) {
        return start + "-" + end + "/" + every;
      } else if (start !== undefined && end !== undefined) {
        return start + "-" + end;
      } else if (start !== undefined && every !== undefined) {
        return start + "/" + every;
      } else if (start !== undefined) {
        return start + "/1";
      } else if (end === undefined && every !== undefined) {
        return "*/" + every;
      } else {
        throw new TypeError(
          `Invalid cron schedule: start=${start}, end=${end}, every=${every}`,
        );
      }
    } else {
      if (typeof exact === "number") {
        return NumberPrototypeToString(exact);
      } else {
        return ArrayPrototypeJoin(exact, ",");
      }
    }
  }
}

function parseScheduleToString(
  schedule: string | Deno.CronSchedule,
): string {
  if (typeof schedule === "string") {
    return schedule;

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Add start: { minute: { start: 0, end: 10 } }.
  2. Use every alone ({ minute: { every: 5 } }) or exact when no range is needed.

Example fix

// before
Deno.cron('n', { hour: { end: 12 } }, fn);
// after
Deno.cron('n', { hour: { start: 0, end: 12 } }, fn);
Defensive patterns

Strategy: type-guard

Validate before calling

for (const [field, spec] of Object.entries(schedule)) {
  if (typeof spec === 'object' && spec.exact === undefined && spec.end !== undefined && spec.start === undefined) {
    throw new Error(`cron field ${field} has end without start`);
  }
}

Type guard

function isValidCronField(v: unknown): boolean {
  if (typeof v === 'number') return true;
  if (typeof v !== 'object' || v === null) return false;
  const r = v as Record<string, unknown>;
  if (r.exact !== undefined) return true;
  if (r.end !== undefined && r.start === undefined) return false; // end-only throws
  return true;
}

Prevention

When it happens

Trigger: Deno.cron('n', { minute: { end: 10 } }) or Deno.cron('n', { minute: { end: 10, every: 2 } }) — end without start and exact undefined.

Common situations: Writing schedule objects from half-remembered syntax; assuming end alone means 'up to the end of the range'.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/e4b9c2ff6888f7b3. Report an issue: GitHub.