sipeed/picoclaw · error
error adding job: %w
Error message
error adding job: %w
What it means
After building the CronSchedule, `picoclaw cron add` calls cron.NewCronService(storePath(), nil).AddJob(...). AddJob appends the job in memory and then persists the whole store with saveStoreUnsafe. This error wraps that persistence (or store-load) failure, so the job was NOT durably added even though the ID logic ran.
Source
Thrown at cmd/picoclaw/internal/cron/add.go:41
Short: "Add a new scheduled job",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
if every <= 0 && cronExp == "" {
return fmt.Errorf("either --every or --cron must be specified")
}
var schedule cron.CronSchedule
if every > 0 {
everyMS := every * 1000
schedule = cron.CronSchedule{Kind: "every", EveryMS: &everyMS}
} else {
schedule = cron.CronSchedule{Kind: "cron", Expr: cronExp}
}
cs := cron.NewCronService(storePath(), nil)
job, err := cs.AddJob(name, schedule, message, channel, to)
if err != nil {
return fmt.Errorf("error adding job: %w", err)
}
fmt.Printf("✓ Added job '%s' (%s)\n", job.Name, job.ID)
return nil
},
}
cmd.Flags().StringVarP(&name, "name", "n", "", "Job name")
cmd.Flags().StringVarP(&message, "message", "m", "", "Message for agent")
cmd.Flags().Int64VarP(&every, "every", "e", 0, "Run every N seconds")
cmd.Flags().StringVarP(&cronExp, "cron", "c", "", "Cron expression (e.g. '0 9 * * *')")
cmd.Flags().StringVar(&to, "to", "", "Recipient for delivery")
cmd.Flags().StringVar(&channel, "channel", "", "Channel for delivery")
_ = cmd.MarkFlagRequired("name")
_ = cmd.MarkFlagRequired("message")
cmd.MarkFlagsMutuallyExclusive("every", "cron")View on GitHub (pinned to 49183d7e8d)
Solutions
- Read the wrapped error: a permission string means fixing ownership of <workspace>/cron/jobs.json; ENOENT means creating the directory
- Ensure the workspace path exists and is writable: `mkdir -p <workspace>/cron`
- If jobs.json is corrupt, move it aside (it is recreated empty) and re-add your jobs
- Re-run `picoclaw cron add ...` and confirm with `picoclaw cron list`
Example fix
# before: cron dir missing, add fails picoclaw cron add -n ping -m hi --every 60 # after mkdir -p "$PICOCLOW_WORKSPACE/cron" picoclaw cron add -n ping -m hi --every 60
Defensive patterns
Strategy: try-catch
Validate before calling
ws=$(picoclaw config path 2>/dev/null) # or read configured workspace mkdir -p "$ws/cron" && [ -w "$ws/cron" ] && echo ok || echo "cron store dir missing/unwritable"
Try / catch
if _, err := cs.AddJob(name, schedule, message, channel, to); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) {
// jobs.json or its dir: create dir / fix ownership, then re-add
}
return fmt.Errorf("add job: %w", err)
} Prevention
- Pre-create <workspace>/cron with correct ownership during provisioning
- Back up jobs.json before workspace migrations
- Treat one failed add as a store problem: verify with `picoclaw cron list` before bulk-adding
When it happens
Trigger: The file <workspace>/cron/jobs.json (path resolved by the cron command's PersistentPreRunE from the config) cannot be created, read, or written: missing cron directory, wrong ownership, disk full, or existing jobs.json is invalid JSON so the initial store load fails.
Common situations: Workspace on a read-only or dropped mount; permissions changed after initial setup; jobs.json truncated by a crash; running the CLI as a different user than the workspace owner.
Related errors
- failed to save config: %w
- failed to save config: %w
- failed to save store: %w
- failed to load config: %w
- reset failed: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/1f337b1408834d6c.
Report an issue: GitHub.