TaskBucket.upsert decided between UPDATE and INSERT based on the number of
rows the UPDATE affected. On MySQL/MariaDB an UPDATE that sets a column to
the value it already holds reports 0 affected rows, so upsert mistook an
existing row for a missing one, ran an INSERT, and hit the
unique(task_id, project_view_id) index with ErrTaskAlreadyExistsInBucket.
This surfaced when marking a task done: the done state is synced into the
done bucket of every kanban view in the project, and if the task already
lived in one of those done buckets the no-op update tripped the bug.
Decide based on row existence instead of the affected-row count, which also
makes the earlier repeating-task workaround unnecessary.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JK7JwuvjhcsNf5d5fUopeY