Summary
The Scans page polling can overlap with manual/filter/page refreshes. If an older request resolves after a newer one, the stale response can overwrite the latest task list and pagination state.
I would like to work on this under GSSoC if maintainers agree with the scope. Please assign this issue to me.
Why this matters
The Scans page is used to monitor task state. Under a slow backend or flaky network, users can switch filters or pages and still see results from a previous request because loadTasks() does not cancel in-flight requests or guard against stale responses.
Reproduction steps
- Open the Scans page.
- Let the initial
/tasks request remain slow.
- Change the status filter or page, which triggers a newer
/tasks request.
- Let the older request resolve after the newer request.
- The older response can call
setTasks() and setTotal() after the newer state has already rendered.
Expected behavior
Only the latest Scans request should update task list and pagination state. Older in-flight requests should be cancelled or ignored.
Actual behavior
Every completed request updates React state, regardless of whether it is still the latest request for the current filter/page.
Scope
- Suggested files or directories:
frontend/src/pages/Scans.tsx:67
frontend/src/pages/Scans.tsx:81
frontend/src/pages/Scans.tsx:102
frontend/src/pages/Scans.tsx:109
frontend/src/pages/Scans.tsx:111
- Related route, page, component, or script:
- Scans page polling
GET /api/v1/tasks
Evidence
The page starts interval polling and calls loadTasks() again whenever filter or page changes. The fetch path updates state directly:
const res = await fetch(`${API_BASE}/tasks?${params.toString()}`);
const data = await res.json();
setTasks(data.tasks || []);
setTotal(data.pagination.total_items);
There is no AbortController, request sequence guard, or mounted-state guard.
Environment
- OS: Any
- Browser: Any
- Python Version: N/A
- Node Version: 20+ project target
- Docker Version: N/A
Definition of done
Additional context
Likely difficulty: intermediate because it touches async UI polling and race-condition behavior. I am not applying labels directly because maintainers/admins handle scoring labels.
Summary
The Scans page polling can overlap with manual/filter/page refreshes. If an older request resolves after a newer one, the stale response can overwrite the latest task list and pagination state.
I would like to work on this under GSSoC if maintainers agree with the scope. Please assign this issue to me.
Why this matters
The Scans page is used to monitor task state. Under a slow backend or flaky network, users can switch filters or pages and still see results from a previous request because
loadTasks()does not cancel in-flight requests or guard against stale responses.Reproduction steps
/tasksrequest remain slow./tasksrequest.setTasks()andsetTotal()after the newer state has already rendered.Expected behavior
Only the latest Scans request should update task list and pagination state. Older in-flight requests should be cancelled or ignored.
Actual behavior
Every completed request updates React state, regardless of whether it is still the latest request for the current filter/page.
Scope
frontend/src/pages/Scans.tsx:67frontend/src/pages/Scans.tsx:81frontend/src/pages/Scans.tsx:102frontend/src/pages/Scans.tsx:109frontend/src/pages/Scans.tsx:111GET /api/v1/tasksEvidence
The page starts interval polling and calls
loadTasks()again wheneverfilterorpagechanges. The fetch path updates state directly:There is no
AbortController, request sequence guard, or mounted-state guard.Environment
Definition of done
Additional context
Likely difficulty: intermediate because it touches async UI polling and race-condition behavior. I am not applying labels directly because maintainers/admins handle scoring labels.