Skip to content

Only successful jobs seem to decrease job_batch.pending_jobs, leading to batches that remain "unfinished" #61835

Open

Description

@stephendnicholas

Laravel Version

13.23.0

PHP Version

8.4.23

Database Driver & Version

sqlite

Description

  • I am submitting a batch of jobs using Bus::batch($jobs)->allowFailures()->finally(...)->dispatch(), onto a queue with a worker running
  • I have a job with use Batchable, Queueable, SerializesModels, InteractsWithQueue; and the attribute #[Tries(1)] (and the associated import) (I have also tried setting public int $tries = 1;)
  • When all of the jobs are successful (i.e. throw no errors), then I see pending_jobs steadily decrease in the job_batches table, and once all jobs are processed, my finally method is called, and I eventually see the job_batches entry updated with a value for finished_at
  • If I make all of the jobs fail (i.e. throw an exception), then I see failed_jobs and failed_job_ids increase, but pending_jobs remains unchanged throughout. Once all jobs have been processed, my finally method is called, but a value for finished_at is never set on the job_batch and pending_jobs still equals total_jobs. I also see entries in the failed_jobs table for each job
  • If I have a mixture of successful and failing jobs, then only the successful ones decrease pending_jobs. Once all jobs have been processed, my finally method is called, but a value for finished_at is never set on the job_batch

Steps To Reproduce

  • Job class defined to only be tried once, and that throws an exception (RuntimeException in my case) in the handle() method
  • Submit a batch of these jobs using Bus::batch($jobs)->allowFailures()->finally(...)->dispatch()
  • Monitor the data in the job_batches table

Activity

  1. stephendnicholas commented on Oct 5, 2026

    @stephendnicholas
    Author

    Hi @shuvroroy,

    Thanks for looking at this so quickly

    I saw your PR and I just wanted to ask a question about the pending_jobs counter: Does it make sense for this to remain the same if failed_jobs has increased?

    Apologies, as I'm new to things in Laravel, but I was kind of expecting behaviour along the lines:

    • When a job succeeds:
      • pending_jobs decreases by 1
      • failed_jobs remains unchanged
    • When a job fails temporarily (and has retries left):
      • pending_jobs does not change
      • failed_jobs does not change
    • When a job fails permanently (all allowed tries exhausted):
      • pending_jobs decreases by 1
      • failed_jobs increases by 1
    • When you retry a batch, for every failed job re-queued:
      • pending_jobs increases by 1
      • and failed_jobs decreases by 1

    Otherwise it seems like we're double counting things?

    (Please feel free to point me elsewhere if this should be a Q & A question or something else)

  2. dwivedianuj9118 commented on Oct 26, 2026

    @dwivedianuj9118

    Hi @stephendnicholas, I don't think it's double counting. The counters are designed around retries:

    • pending_jobs counts jobs that haven't succeeded yet. A failed job stays in it on purpose, so it can still be retried with php artisan queue:retry-batch {id}. When a retried job succeeds, pending_jobs goes down and its ID is removed from failed_job_ids.
    • failed_jobs counts recorded failures. It's incremented when a job fails and isn't decremented on retry; only failed_job_ids is updated.

    The batch then uses two different completion checks:

    • pending_jobs === failed_jobs means every job has run once, so finally() fires (UpdatedBatchJobCounts::allJobsHaveRanExactlyOnce()).
    • pending_jobs === 0 means every job succeeded, so finished_at is set and then() fires.

    That's why your all-failing batch runs finally() but never gets finished_at. #61850 proposed changing that and was closed, so it's the current behaviour. In the meantime:

    • Use finally() to run your "done" logic, or check $batch->pendingJobs === $batch->failedJobs and $batch->hasFailures().
    • Use php artisan queue:prune-batches --unfinished=72 so these batches still get pruned.
  3. added a commit that references this issue on Oct 28, 2026
    c67e675
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions