{"record":{"id":"1f337b1408834d6c","repo":"sipeed/picoclaw","slug":"error-adding-job-w","errorCode":null,"errorMessage":"error adding job: %w","messagePattern":"error adding job: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/cron/add.go","lineNumber":41,"sourceCode":"\t\tShort: \"Add a new scheduled job\",\n\t\tArgs:  cobra.NoArgs,\n\t\tRunE: func(cmd *cobra.Command, _ []string) error {\n\t\t\tif every <= 0 && cronExp == \"\" {\n\t\t\t\treturn fmt.Errorf(\"either --every or --cron must be specified\")\n\t\t\t}\n\n\t\t\tvar schedule cron.CronSchedule\n\t\t\tif every > 0 {\n\t\t\t\teveryMS := every * 1000\n\t\t\t\tschedule = cron.CronSchedule{Kind: \"every\", EveryMS: &everyMS}\n\t\t\t} else {\n\t\t\t\tschedule = cron.CronSchedule{Kind: \"cron\", Expr: cronExp}\n\t\t\t}\n\n\t\t\tcs := cron.NewCronService(storePath(), nil)\n\t\t\tjob, err := cs.AddJob(name, schedule, message, channel, to)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error adding job: %w\", err)\n\t\t\t}\n\n\t\t\tfmt.Printf(\"✓ Added job '%s' (%s)\\n\", job.Name, job.ID)\n\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tcmd.Flags().StringVarP(&name, \"name\", \"n\", \"\", \"Job name\")\n\tcmd.Flags().StringVarP(&message, \"message\", \"m\", \"\", \"Message for agent\")\n\tcmd.Flags().Int64VarP(&every, \"every\", \"e\", 0, \"Run every N seconds\")\n\tcmd.Flags().StringVarP(&cronExp, \"cron\", \"c\", \"\", \"Cron expression (e.g. '0 9 * * *')\")\n\tcmd.Flags().StringVar(&to, \"to\", \"\", \"Recipient for delivery\")\n\tcmd.Flags().StringVar(&channel, \"channel\", \"\", \"Channel for delivery\")\n\n\t_ = cmd.MarkFlagRequired(\"name\")\n\t_ = cmd.MarkFlagRequired(\"message\")\n\tcmd.MarkFlagsMutuallyExclusive(\"every\", \"cron\")","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/cron/add.go#L23-L59","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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`"],"exampleFix":"# before: cron dir missing, add fails\npicoclaw cron add -n ping -m hi --every 60\n# after\nmkdir -p \"$PICOCLOW_WORKSPACE/cron\"\npicoclaw cron add -n ping -m hi --every 60","handlingStrategy":"try-catch","validationCode":"ws=$(picoclaw config path 2>/dev/null) # or read configured workspace\nmkdir -p \"$ws/cron\" && [ -w \"$ws/cron\" ] && echo ok || echo \"cron store dir missing/unwritable\"","typeGuard":null,"tryCatchPattern":"if _, err := cs.AddJob(name, schedule, message, channel, to); err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) {\n        // jobs.json or its dir: create dir / fix ownership, then re-add\n    }\n    return fmt.Errorf(\"add job: %w\", err)\n}","preventionTips":["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"],"tags":["cron","cli","filesystem","persistence"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}