Skip to content

[BUG] Recurring cron jobs (every_seconds / cron_expr) silently become one-time "at" tasks #1043

@AaronJny

Description

@AaronJny

Description

All cron jobs created with every_seconds or cron_expr are silently stored as
one-time schedule.kind: "at" tasks with deleteAfterRun: true. They execute
once and are then deleted.

Steps to Reproduce

  1. Ask PicoClaw to create a recurring task (e.g., "remind me every 2 hours to drink water")
  2. Inspect ~/.picoclaw/workspace/cron/jobs.json
  3. Observe: schedule.kind is "at", deleteAfterRun is true

Root Cause

In pkg/tools/cron.go, the addJob function uses Go type assertions:

atSeconds, hasAt := args["at_seconds"].(float64)

LLMs frequently fill unused optional parameters with default values (e.g.,
at_seconds: 0). Go's type assertion returns (0, true) for zero values, so
hasAt is always true. Since at_seconds has the highest priority in the
if-else chain, it always wins — turning all recurring tasks into one-time tasks
that run immediately (0 seconds from now).

Proposed Fix

Add value validity checks after type assertions (3 lines):

hasAt = hasAt && atSeconds > 0
hasEvery = hasEvery && everySeconds > 0
hasCron = hasCron && cronExpr != ""

This has zero risk of regression — legitimate at_seconds > 0 values continue
to work exactly as before.

Environment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions