nexu-io/open-design · error · Error

--schedule hourly requires :<minute>, 0-59

Error message

--schedule hourly requires :<minute>, 0-59

What it means

Thrown by parseScheduleFlag for the `hourly` kind when the minute part is missing, non-numeric, or outside 0-59. The check is `Number.isInteger(minute) && minute >= 0 && minute <= 59`. The schedule format is `hourly:<minute>`.

Source

Thrown at apps/daemon/src/cli.ts:10501

// external agent (hermes-agent, openclaw, custom Slackbot, etc.) can run
// the full lifecycle — list, create, fire, harvest, retire — without
// rendering a page. Storage is /api/routines on the local daemon; the
// "routine" name is the implementation detail, "automation" is the user-
// facing surface.
// ---------------------------------------------------------------------------

function parseScheduleFlag(raw) {
  if (!raw || typeof raw !== 'string') {
    throw new Error(
      '--schedule is required. Forms: hourly:<minute> | daily:HH:MM[:TZ] | weekdays:HH:MM[:TZ] | weekly:DAY:HH:MM[:TZ]',
    );
  }
  const parts = raw.split(':');
  const kind = parts[0];
  if (kind === 'hourly') {
    const minute = Number(parts[1]);
    if (!Number.isInteger(minute) || minute < 0 || minute > 59) {
      throw new Error('--schedule hourly requires :<minute>, 0-59');
    }
    return { kind: 'hourly', minute };
  }
  if (kind === 'daily' || kind === 'weekdays') {
    if (parts.length < 3) {
      throw new Error(`--schedule ${kind} requires :HH:MM[:TZ]`);
    }
    const hh = parts[1];
    const mm = parts[2];
    const time = `${hh.padStart(2, '0')}:${mm.padStart(2, '0')}`;
    if (!/^[0-2]\d:[0-5]\d$/.test(time)) {
      throw new Error(`--schedule ${kind} time must be HH:MM (24h)`);
    }
    const timezone = parts.slice(3).join(':') || 'UTC';
    return { kind, time, timezone };
  }
  if (kind === 'weekly') {
    if (parts.length < 4) {

View on GitHub (pinned to 5be4028344)

Solutions

  1. Use `--schedule hourly:<minute>` with an integer 0-59, e.g. `hourly:30` to run on the half-hour.
  2. If you meant a specific time of day, switch to `daily:HH:MM[:TZ]` instead.
  3. Double-check the value is an integer — leading zeros are fine, decimals are not.
  4. Use --help to confirm the hourly grammar.

Example fix

# before
od automation create --name h --prompt-file p.txt --schedule hourly:60
# after
od automation create --name h --prompt-file p.txt --schedule hourly:30
Defensive patterns

Strategy: validation

Validate before calling

function parseHourlyMinute(raw) {
  const m = /^hourly:(\d{1,2})$/.exec(raw);
  const minute = m ? Number(m[1]) : NaN;
  if (!Number.isInteger(minute) || minute < 0 || minute > 59) {
    throw new Error('--schedule hourly requires :<minute>, 0-59');
  }
  return minute;
}

Type guard

const isHourlyMinute = (v: unknown): boolean => {
  if (typeof v !== 'string') return false;
  const m = /^hourly:(\d{1,2})$/.exec(v);
  const n = m ? Number(m[1]) : NaN;
  return Number.isInteger(n) && n >= 0 && n <= 59;
};

Prevention

When it happens

Trigger: `--schedule hourly`, `--schedule hourly:`, `--schedule hourly:60`, `--schedule hourly:abc`, or `--schedule hourly:-5`.

Common situations: Forgetting the minute component; using 24-hour-style '60' for the top of the hour; passing a fractional minute; copy-paste error from a daily schedule that left HH:MM in place.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/30e654f70311df19. Report an issue: GitHub.