Description
Retrying a discarded unique job while another active job with the same unique
properties exists causes the retry endpoint to return HTTP 500. The UI then
replaces the current page with an error/blank screen instead of displaying an
actionable notification.
The retry is expected to fail because of the uniqueness constraint, but the
failure should be handled gracefully.
Versions
- River UI: v0.16.0
- River: v0.35.1
- PostgreSQL: 17
Steps to reproduce
- Insert a job with uniqueness enabled.
- Let that job reach the
discarded state.
- Insert another active job with the same unique properties.
- Open the discarded job in River UI.
- Click Retry.
Actual behavior
POST /api/jobs/retry returns:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{"message":"Internal server error. Check logs for more information."}
The River UI logs contain:
ERROR: duplicate key value violates unique constraint "river_job_unique_idx"
SQLSTATE 23505
The frontend mutation uses throwOnError: true, so the error reaches the route
error boundary and the current jobs page is replaced by an error/blank screen.
The same behavior occurs for retrying a single job and retrying selected jobs
from the job list.
## Expected behavior
- Keep the current jobs page open.
- Display an error toast with an actionable explanation.
- Treat river_job_unique_idx as an expected conflict, possibly returning
HTTP 409 instead of HTTP 500.
For example:
> Job cannot be retried because another active job has the same unique
> properties. Wait for it to finish or delete it before retrying.
## Possible fix
- Handle retry mutation failures with onError instead of
throwOnError: true.
- Detect PostgreSQL unique violations for river_job_unique_idx in the retry
endpoint and return an actionable API error.
Description
Retrying a discarded unique job while another active job with the same unique
properties exists causes the retry endpoint to return HTTP 500. The UI then
replaces the current page with an error/blank screen instead of displaying an
actionable notification.
The retry is expected to fail because of the uniqueness constraint, but the
failure should be handled gracefully.
Versions
Steps to reproduce
discardedstate.Actual behavior
POST /api/jobs/retryreturns: