Phantom-success writes: muse hub issue create silently lost a row, letting a later create reuse its number
Fixed — root cause confirmed and closed via direct reproduction
Directly reproduced the race, live on staging: 10 concurrent muse hub issue create calls against the same repo produced genuine duplicate numbers (3 rows at #199, 2 rows at #197, confirmed via a direct DB query — all 10 rows persisted, nothing was silently lost, the numbers just collided). Locally, with the fix reverted to prove the regression test is real, all 10 concurrent creates collided on #1.
Important scope note: this confirms and fixes a real, critical, independently-reproducible race condition in _next_issue_number — but it does not fully explain the original incident that opened this ticket (a single row silently vanishing with no duplicate ever appearing). That remains a distinct, still-unexplained failure mode. Both bugs share a superficial resemblance (per-repo issue numbering going wrong under concurrency), but the reproduced race produces duplicates, not data loss. Worth keeping open as its own investigation if it recurs — for now, this fix closes the concrete, reproducible bug.
Fix (belt and suspenders)
musehub/services/musehub_issues.py::_next_issue_numbernow locks the repo row (SELECT ... FOR UPDATE) before computingMAX(number), serializing concurrent allocation for the same repo within the same transaction that later inserts and commits.- Migration
0076:UNIQUEconstraint onmusehub_issues(repo_id, number)as a backstop — any future code path that bypasses the lock now fails loudly (IntegrityError) instead of silently producing a duplicate. Verified staging had zero existing duplicates before applying (required for the migration to succeed). - Caught a real deploy-time gap along the way: the migration alone wasn't enough — the SQLAlchemy ORM model needed the matching
UniqueConstraintdeclared too, or the schema-drift gate correctly refuses to deploy. Fixed and redeployed.
Test
tests/test_musehub_issues.py::test_concurrent_creates_never_produce_duplicate_issue_numbers — fires 10 real concurrent creates via the test HTTP client against a real Postgres-backed test DB, asserts all 10 numbers are distinct, asserts zero duplicate (repo_id, number) rows via direct DB query, and asserts all 10 rows persisted. Confirmed genuinely red without the fix (all 10 collide on #1) and green with it.
Live verification
Deployed to staging, then fired 8 fresh concurrent creates against the real API — all 8 got distinct numbers (192–199), zero collisions. Test data cleaned up afterward.
Closing this ticket now that the confirmed, reproducible bug is fixed, tested, and verified live.