Skip to content

fix tasks bulk delete freezing app when selecting more than 500 tasks#7515

Merged
kodjima33 merged 2 commits into
mainfrom
fix/bulk-delete-tasks-over-500
May 28, 2026
Merged

fix tasks bulk delete freezing app when selecting more than 500 tasks#7515
kodjima33 merged 2 commits into
mainfrom
fix/bulk-delete-tasks-over-500

Conversation

@krushnarout
Copy link
Copy Markdown
Member

@krushnarout krushnarout commented May 27, 2026

Summary

  • Removed max_length=500 from BatchDeleteActionItemsRequest — Pydantic was rejecting requests with >500 IDs with a 422, causing Flutter to roll back the optimistic deletion and leaving the UI frozen with all tasks still visible
  • Replaced the hard ValueError guard in delete_action_items_batch with chunked Firestore batch commits (500 ops per commit), matching the pattern already used by batch_update_action_items in the same file
  • Downstream cleanup (send_action_items_batch_deletion_message, delete_action_item_vectors_batch) already handles arbitrary list sizes — no changes needed there

Test plan

  • Select all tasks (500+) and tap delete — tasks should disappear without the app freezing
  • Select a subset <500 tasks and delete — should work as before
  • Ask AI chat to delete all tasks — should complete successfully

Closes #7271

🤖 Generated with Claude Code

The batch-delete endpoint capped requests at 500 IDs via Pydantic
max_length, causing a 422 for larger selections. Flutter treated the
non-200 as a failure and rolled back the optimistic deletion, freezing
the UI with all tasks still visible.

Removed the max_length cap from the request model and replaced the
hard ValueError guard in the DB layer with chunked Firestore batch
commits (500 ops per commit), matching the pattern already used by
batch_update_action_items.

Closes #7271

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 27, 2026

Greptile Summary

This PR fixes a UI freeze that occurred when bulk-deleting more than 500 tasks by replacing a hard 500-item Firestore batch limit with a chunked commit loop, and removing the corresponding Pydantic max_length=500 cap that was causing 422 rejections.

  • backend/database/action_items.py: delete_action_items_batch now iterates through all IDs and commits a new Firestore batch every 500 operations, mirroring the pattern already used by batch_update_action_items. The previous all-or-nothing atomicity guarantee is intentionally traded for support of arbitrarily large deletions.
  • backend/routers/action_items.py: BatchDeleteActionItemsRequest.ids drops max_length=500, allowing the endpoint to accept any number of IDs and pass them through to the chunked DB layer.

Confidence Score: 4/5

Safe to merge for the bulk-delete bug fix; the only open question is whether the completely unbounded request size is acceptable long-term.

The chunking logic is straightforward and mirrors an existing pattern in the same file. The main concern is that removing max_length entirely leaves no guardrail against very large payloads, but this is a hardening question rather than a current breakage. A minor threshold inconsistency (500 vs 499) exists between the two batch functions but does not affect correctness.

backend/routers/action_items.py — the removal of any upper bound on the IDs list deserves a second look.

Important Files Changed

Filename Overview
backend/database/action_items.py Replaces the single-batch (≤500) delete with a chunked loop that commits every 500 ops, matching the pattern in batch_update_action_items; minor inconsistency in threshold (500 vs 499) compared to sibling function.
backend/routers/action_items.py Drops max_length=500 from BatchDeleteActionItemsRequest, unblocking >500 bulk deletes; leaves the endpoint with no upper bound on list size.

Sequence Diagram

sequenceDiagram
    participant Flutter
    participant Router as POST /v1/action-items/batch-delete
    participant DB as delete_action_items_batch
    participant FS as Firestore

    Flutter->>Router: "ids: [id1…idN] (N > 500)"
    Router->>DB: delete_action_items_batch(uid, ids)
    loop every 500 ids
        DB->>FS: batch.commit() (up to 500 deletes)
        FS-->>DB: OK
    end
    DB-->>Router: deleted_ids
    Router->>Router: delete_action_item_vectors_batch
    Router->>Router: send_action_items_batch_deletion_message
    Router-->>Flutter: "{status: Ok, deleted_count: N}"
Loading

Reviews (1): Last reviewed commit: "fix(tasks): support bulk delete of more ..." | Re-trigger Greptile

Comment thread backend/database/action_items.py Outdated
batch.delete(action_items_ref.document(item_id))
batch.commit()
count += 1
if count >= 500:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Threshold inconsistency with sibling function

batch_update_action_items in the same file uses count >= 499 to stay safely under the 500-op Firestore limit (commits when 499 ops are queued), but this new code uses count >= 500. While committing a batch of exactly 500 ops is technically within the limit, the off-by-one inconsistency is surprising and could trip up a future reader who expects the two functions to match. Consider aligning both to >= 499 for consistency.

Comment thread backend/routers/action_items.py Outdated

class BatchDeleteActionItemsRequest(BaseModel):
ids: List[str] = Field(description="IDs of action items to delete", min_length=1, max_length=500)
ids: List[str] = Field(description="IDs of action items to delete", min_length=1)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No upper bound on request size

Removing max_length=500 leaves the endpoint with no cap on list size. A caller can now submit tens of thousands of IDs in a single request, which will loop through all of them on the main thread, block the worker for the full duration of N/500 sequential Firestore commits, and hold the entire payload in memory. Consider replacing the old 500-cap with a higher but still finite limit (e.g. max_length=10000) to prevent accidental or malicious overloads while still allowing bulk operations well beyond the old limit.

- Add max_length=10000 to BatchDeleteActionItemsRequest to prevent
  unbounded payloads while supporting any realistic task count
- Align delete batch threshold to count >= 499 to match the sibling
  batch_update_action_items pattern in the same file

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@krushnarout krushnarout requested a review from mdmohsin7 May 27, 2026 17:20
@kodjima33 kodjima33 merged commit 63e3272 into main May 28, 2026
2 checks passed
@kodjima33 kodjima33 deleted the fix/bulk-delete-tasks-over-500 branch May 28, 2026 23:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bulk delete tasks fails

2 participants