Skip to content

Recurring cron jobs silently skip when next_run_at is null #5518

@fgallese

Description

@fgallese

Bug

In cron/jobs.py, get_due_jobs() uses _recoverable_oneshot_run_at() to recover jobs with null next_run_at. This function only handles one-shot jobs — for recurring cron/interval jobs, it returns None, causing the job to be silently skipped via continue.

Any recurring cron job that ends up with next_run_at: null (after updates, restarts, or manual edits to jobs.json) will never fire again until the user manually sets next_run_at.

Reproduction

  1. Create a recurring cron job (e.g. 0 21 * * 0-4)
  2. Set its next_run_at to null in jobs.json (or trigger it via restart/update)
  3. The job silently stops firing — no error, no warning

Expected behavior

For recurring cron/interval jobs with null next_run_at, compute_next_run() should be called to recompute the next run time instead of falling through to the one-shot recovery path.

Suggested fix

next_run = job.get("next_run_at")
if not next_run:
    schedule = job.get("schedule", {})
    kind = schedule.get("kind")
    if kind in ("cron", "interval"):
        recovered_next = compute_next_run(schedule, now.isoformat())
    else:
        recovered_next = _recoverable_oneshot_run_at(
            schedule, now, last_run_at=job.get("last_run_at"),
        )
    if not recovered_next:
        continue
    ...

Environment

  • Hermes Agent v0.7.0+
  • cron/jobs.py, get_due_jobs() function around line 668

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — major feature broken, no workaroundcomp/cronCron scheduler and job managementtype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions