Hangfire Pro: continuation for batch is not executed if some of the batch jobs fail


I’m trying to enqueue a continuation job after a batch has finished. BatchContinuationOptions is “OnAnyFinishedState” which means it should run even if some of the batch jobs have failed. However, the continuation job runs only if ALL of the batch jobs completed successfully. It looks like a bug to me or maybe I miss something here. Below is the source code:

class Program
    static void Main(string[] args)
        GlobalConfiguration.Configuration.UseSqlServerStorage(@"Server=.\sqlexpress; Database=MyJobs; Integrated Security=SSPI;");
        using (new BackgroundJobServer())
            Console.WriteLine("Started Test");
    private static void RunBatch()
        const int jobsCount = 3;
        var batchId = BatchJob.StartNew(x =>
            for (var i = 0; i < jobsCount; i++)
                int jobNumber = i;
                x.Enqueue(() => new MyJob().Run(jobNumber));
        BatchJob.ContinueWith(batchId, x =>
                x.Enqueue(() => Console.WriteLine("Executing continuation for batch " + batchId));
    [AutomaticRetry(Attempts = 0)]
    public class MyJob
        public void Run(int jobNumber)
            Console.WriteLine("Executing job " + jobNumber);
            throw new ArgumentException("Failure!");

Used packages:
package id=“Hangfire.Core” version=“1.5.2” targetFramework=“net452”
package id=“Hangfire.Pro” version=“1.4.3” targetFramework=“net452”
package id=“Hangfire.SqlServer” version=“1.5.2” targetFramework=“net452”
package id=“Newtonsoft.Json” version=“5.0.1” targetFramework=“net452”
package id=“Owin” version=“1.0” targetFramework=“net452”

Hi @vladn. This is because Failed state is not a final one. Point is that background jobs in a final state are expired and removed from the storage. If there was an exception, it is unclear when to expire a job, in 24 hours, in a week, etc. It is more useful to visit a dashboard even after a month and see there were problems – Hangfire doesn’t know, if your exception was expected.

However, you can tell Hangfire to forget about a background job after all attempts were exceeded, just place the following attribute on your method:

[AutomaticRetry(OnAttemptsExceeded = AttemptsExceededAction.Delete)]

In this case, background job will be moved to the DeletedState after some attempts, and this state is the final one. So your continuation will be fired.

OK, thanks. From this perspective it makes sense