{"record":{"id":"3ebec5dc45abe7ea","repo":"chenhg5/cc-connect","slug":"reschedule-failed-w","errorCode":null,"errorMessage":"reschedule failed: %w","messagePattern":"reschedule failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/cron.go","lineNumber":606,"sourceCode":"\t\tcs.mu.Lock()\n\t\tif entryID, ok := cs.entries[id]; ok {\n\t\t\tcs.cron.Remove(entryID)\n\t\t\tdelete(cs.entries, id)\n\t\t}\n\t\tcs.mu.Unlock()\n\t}\n\n\t// Update the field\n\tif !cs.store.Update(id, field, value) {\n\t\treturn fmt.Errorf(\"failed to update field %q (may be read-only or invalid type)\", field)\n\t}\n\n\t// Reschedule if needed\n\tif needsReschedule {\n\t\tupdatedJob := cs.store.Get(id)\n\t\tif updatedJob != nil && updatedJob.Enabled {\n\t\t\tif err := cs.scheduleJob(updatedJob); err != nil {\n\t\t\t\treturn fmt.Errorf(\"reschedule failed: %w\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (cs *CronScheduler) Store() *CronStore {\n\treturn cs.store\n}\n\n// NextRun returns the next scheduled run time for a job, or zero if not scheduled.\nfunc (cs *CronScheduler) NextRun(jobID string) time.Time {\n\tcs.mu.RLock()\n\tentryID, ok := cs.entries[jobID]\n\tcs.mu.RUnlock()\n\tif !ok {\n\t\treturn time.Time{}","sourceCodeStart":588,"sourceCodeEnd":624,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/cron.go#L588-L624","documentation":"After successfully persisting the field change, UpdateJob reschedules the cron entry when the change affects firing (cron_expr or enabled). If cs.scheduleJob returns an error, the store already has the new value but the in-memory timer could not be updated, so the error is wrapped with \"reschedule failed\".","triggerScenarios":"Updating cron_expr to an invalid expression that scheduleJob cannot parse, or enabling a job whose schedule cannot be computed — any scheduleJob failure after a successful store.Update.","commonSituations":"User edits a job to a malformed cron expression via handleCronEdit; the new expression was accepted by the store but rejected by the scheduler.","solutions":["Validate the cron expression with the same parser scheduleJob uses before calling UpdateJob","Retry with a valid cron_expr value; the stored state is already updated so only the timer needs fixing","Check scheduler logs/next-fire time; restarting the daemon will rebuild timers from the store"],"exampleFix":"// before\ncs.UpdateJob(id, \"cron_expr\", \"99 * * * *\") // invalid expression\n// after\nif parser.Valid(\"99 * * * *\") == false { return errors.New(\"invalid cron expression\") }\ncs.UpdateJob(id, \"cron_expr\", \"0 * * * *\")","handlingStrategy":"validation","validationCode":"if field == \"cron_expr\" {\n    if _, err := cron.ParseStandard(expr); err != nil { return err }\n}","typeGuard":null,"tryCatchPattern":"if err := cs.UpdateJob(id, \"cron_expr\", expr); err != nil {\n    var wrapped error\n    if errors.Unwrap(err) != nil { wrapped = err }\n    slog.Error(\"cron reschedule failed; store updated but timer not rebuilt\", \"id\", id, \"err\", err)\n    _ = wrapped\n}","preventionTips":["Validate cron expressions with the same parser the scheduler uses before persisting","After a reschedule failure, verify next-fire time or restart the daemon to rebuild timers"],"tags":["go","cron","scheduling"],"backgroundTag":"invalid-config-value","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}