-
Notifications
You must be signed in to change notification settings - Fork 614
[BUG][UI]: Race condition in deleteTeamSafe causes stale team list after deletion #2864
Description
Description
After deleting a team via the "Delete Team" button, the team list briefly (or persistently) shows stale data — the deleted team still appears in the list even though it was successfully removed on the server.
Root Cause
deleteTeamSafe() in admin.html triggers a double-refresh pattern that races with the database transaction:
htmx.ajax('DELETE', '/admin/teams/' + teamId, {
target: '#unified-teams-list',
swap: 'innerHTML'
}).then(() => {
initializeTeamManagement(); // Refresh #1: fires ~41ms after DELETE response
});The backend DELETE handler also returns an HX-Trigger header:
response.headers["HX-Trigger"] = orjson.dumps({
"adminTeamAction": {"refreshUnifiedTeamsList": True, "delayMs": 1000}
}).decode()This results in 3 competing operations targeting #unified-teams-list:
- DELETE response (t=0): Swaps a success message into the list container
.then()GET (t+~41ms): Fetches the team list — may return stale data if the DB transaction hasn't fully committed- HX-Trigger GET (t+~1035ms): Fetches the team list again — also may return stale data
Observed Behavior
- Tested with Playwright against Docker deployment (nginx → gateway)
- Deleted
PaginationTest-17from page 2 — page continued showing it with "15 items" - Server confirmed deletion (fetch to
/admin/teams/partial?page=1&per_page=100returned 14 teams, PaginationTest-17 absent) - Manual refresh via
htmx.ajaxcorrectly showed updated list with 14 items - Same behavior observed when deleting
PaginationTest-18
Expected Behavior
After deleting a team, the team list should refresh and show the updated list without the deleted team.
Affected Functions
The same double-refresh pattern exists in multiple functions in admin.html:
deleteTeamSafe()(~line 14703)leaveTeamSafe()(~line 14654)cancelJoinRequest()(~line 14716)
All follow the pattern: htmx.ajax(...).then(() => initializeTeamManagement()) while the backend also fires adminTeamAction via HX-Trigger.
Suggested Fix
Two options:
Option A (minimal): Remove the .then(() => initializeTeamManagement()) from these functions and rely solely on the HX-Trigger event handler (handleAdminTeamAction) for refreshing. Increase the delay slightly to ensure the transaction has committed.
Option B (robust): Add a small delay before the refresh to allow the DB transaction to commit:
htmx.ajax('DELETE', '/admin/teams/' + teamId, {
target: '#unified-teams-list',
swap: 'innerHTML'
}).then(() => {
setTimeout(() => initializeTeamManagement(), 500);
});Environment
- Docker deployment with nginx reverse proxy
- SQLite database (may also affect PostgreSQL with different transaction isolation)
- Tested on branch
2799-stay-on-the-same-page-when-updating-teams