makeplane / makeplane/plane

cycles: transfer_cycle_issues non-atomic - progress_snapshot saved but issues not moved if process killed mid-transfer

Open Beginner friendly
#9,599 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
59.6k
Forks
5.8k
Avg merge
1d 22h
Merged PRs (30d)
49

Description

Bug Description

ransfer_cycle_issues performs two DB writes sequentially without wrapping them in 	ransaction.atomic. If the process is killed or a DB error occurs after the first write completes but before the second, the database is left in an inconsistent state with no recovery path.

Affected file

pps/api/plane/utils/cycle_transfer_issues.py:

`python
current_cycle.save(update_fields=["progress_snapshot"]) # line 432 - committed first

... build updated_cycles list ...

CycleIssue.objects.bulk_update(updated_cycles, ["cycle_id"], batch_size=100) # line 458 - may never run
`

Failure scenario

  1. Admin triggers "Transfer incomplete issues" from cycle A to cycle B.
  2. current_cycle.save(update_fields=["progress_snapshot"]) commits - cycle A now appears complete in the UI.
  3. Worker process is killed (OOM kill, deploy restart, DB connection timeout) before CycleIssue.objects.bulk_update runs.
  4. Cycle A shows as completed with a snapshot, but all its issues still belong to cycle A - they were never moved.
  5. Users see a "completed" cycle full of issues with no way to trigger the transfer again through the UI.

Fix

`python
from django.db import transaction

with transaction.atomic():
current_cycle.save(update_fields=["progress_snapshot"])
CycleIssue.objects.bulk_update(updated_cycles, ["cycle_id"], batch_size=100)
`

Environment

Plane develop branch (2026-08-13).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/api/plane/utils/cycle_transfer_issues.py at transfer_cycle_issues and inspect the two writes around lines 432 and 458. Verify that the progress snapshot and CycleIssue updates share one transaction, and confirm that a failure between them does not leave the cycle marked complete while its issues remain unmoved.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, python
Domain
database
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.