From 88af565ca32d5cf3c07dd8b61dae51dbc4f42cc5 Mon Sep 17 00:00:00 2001 From: wintan1418 Date: Tue, 18 Aug 2026 20:13:30 +0100 Subject: [PATCH] Document that retry_on can't intercept process-death errors Active Job's retry_on and rescue_from only hook into exceptions raised while perform runs. ProcessPrunedError, ProcessExitError and ProcessMissingError are never raised inside the job: the process running it is already gone, and a different process records the error directly as a failed execution after the fact. People coming from other backends expect retry_on to cover this case and are surprised when it silently doesn't, so spell out why it can't work and point to the mechanisms that do: Mission Control and the fail_many_claimed subscription. Fixes #786 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 54a09248..d9c8b484 100644 --- a/README.md +++ b/README.md @@ -669,6 +669,8 @@ end When a process dies without a clean shutdown (for example, `SIGKILL`ed by the OS or the container runtime because of memory limits), the jobs it was running can't be released back to their queues. Once another process notices the missing heartbeats and prunes the dead process's registration, its in-flight jobs are marked as failed with `SolidQueue::Processes::ProcessPrunedError`. Solid Queue deliberately doesn't retry these automatically: the job itself might be what's killing the process (for example, a job that exhausts the container's memory), and retrying it blindly would just kill the next worker too. +Note that Active Job's `retry_on` and `rescue_from` have no effect on these errors: they only intercept exceptions raised while your job's `perform` method runs, and `ProcessPrunedError` (as well as `ProcessExitError` and `ProcessMissingError`) is never raised inside the job. The process that was running the job is gone by then — the error is recorded directly as a failed execution by a *different* process, after the fact, so there's no job execution left for Active Job's retry machinery to hook into. To retry these jobs, act on the failed executions from the outside instead: manually, via [Mission Control — Jobs](https://github.com/rails/mission_control-jobs), or automatically, with a subscription like the one below. + If you know your jobs are idempotent and want to implement your own recovery policy, you can subscribe to the `fail_many_claimed.solid_queue` event, which includes the error and the affected job IDs in its payload: ```ruby