[Bug] Publishing a workflow resets schedule next_run_at even when cron/timezone did not change
- Dominant language
- TypeScript
- Stars
- 156k
- Forks
- 24.6k
- Avg merge
- 22h 9m
- Merged PRs (30d)
- 610
Description
### Self Checks
- [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
- [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
- [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
- [x] I confirm that I am using English to submit this report, otherwise it will be closed.
- [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
- [x] Please do not modify this template :) and fill in all the required fields.
### Dify version
main (1.17.x)
### Cloud or Self Hosted
Self Hosted (Docker)
### Steps to reproduce
1. Publish a workflow with a schedule trigger (e.g. cron `*/10 * * * *`).
2. Note `workflow_schedule_plans.next_run_at` (suppose it is 2 minutes from now).
3. Make an unrelated edit (or republish the same graph without changing the schedule node) and publish again.
4. Check `next_run_at` again.
### ✔️ Expected Behavior
If `cron_expression` and `timezone` are unchanged, `next_run_at` stays as-is so an imminent due run is not skipped.
### ❌ Actual Behavior
`sync_schedule_from_workflow` always builds a `SchedulePlanUpdate` with non-`None` `cron_expression` / `timezone`. `ScheduleService.update_schedule` treats any non-`None` time field as changed and recalculates `next_run_at` from “now”, which can skip a pending fire that was about to run.
Related in spirit to #41214 (reported cron string mutation), but this issue is specifically the always-rewrite of `next_run_at` even when the schedule config is identical.
### Root cause (current main)
- `api/events/event_handlers/sync_workflow_schedule_when_app_published.py` always passes cron/timezone
- `api/services/trigger/schedule_service.py` sets `time_fields_updated = True` whenever those fields are not `None`, without comparing to the existing values
### Suggested fix
Only mark time fields updated when the new value differs from the stored value (or skip `update_schedule` entirely when nothing changed).
Contributor guide
Assessment
This issue has not been assessed yet.