HangfireIO/Hangfire · error · InvalidOperationException

Multiple provider instances registered for queues: {String.J

Error message

Multiple provider instances registered for queues: {String.Join(", ", queues)}. You should choose only one type of persistent queues per server instance.

What it means

InvalidOperationException thrown by SqlServerConnection.FetchNextJob when the queues requested map to more than one distinct IPersistentQueueProvider. A single Dequeue call must come from one provider; mixing providers (e.g. SQL Server native queues and MSMQ queues) in the same fetch list is rejected.

Source

Thrown at src/Hangfire.SqlServer/SqlServerConnection.cs:81

        public override IDisposable AcquireDistributedLock([NotNull] string resource, TimeSpan timeout)
        {
            if (String.IsNullOrWhiteSpace(resource)) throw new ArgumentNullException(nameof(resource));
            return AcquireLock($"{_storage.SchemaName}:{resource}", timeout);
        }

        public override IFetchedJob FetchNextJob(string[] queues, CancellationToken cancellationToken)
        {
            if (queues == null || queues.Length == 0) throw new ArgumentNullException(nameof(queues));

            var providers = queues
                .Select(queue => _storage.QueueProviders.GetProvider(queue))
                .Distinct()
                .ToArray();

            if (providers.Length != 1)
            {
                throw new InvalidOperationException(
                    $"Multiple provider instances registered for queues: {String.Join(", ", queues)}. You should choose only one type of persistent queues per server instance.");
            }
            
            var persistentQueue = providers[0].GetJobQueue();
            return persistentQueue.Dequeue(queues, cancellationToken);
        }

        public override string CreateExpiredJob(
            Job job,
            IDictionary<string, string> parameters, 
            DateTime createdAt,
            TimeSpan expireIn)
        {
            if (job == null) throw new ArgumentNullException(nameof(job));
            if (parameters == null) throw new ArgumentNullException(nameof(parameters));

            var queryString = _storage.GetQueryFromTemplate(static schemaName =>
$@"insert into [{schemaName}].Job (InvocationData, Arguments, CreatedAt, ExpireAt)

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Give each BackgroundJobServer a queues array that resolves to exactly one provider, and split mixed workloads across separate server instances.
  2. Review QueueProviders registrations and the queues array to ensure all entries map to the same provider.
  3. If you migrated a queue from one provider to another, remove the old registration so names no longer collide.

Example fix

// before
var options = new BackgroundJobServerOptions { Queues = new[] { "default", "msmq-queue" } };

// after (one provider per server)
var sqlServer  = new BackgroundJobServer(new BackgroundJobServerOptions { Queues = new[] { "default" } });
var msmqServer = new BackgroundJobServer(new BackgroundJobServerOptions { Queues = new[] { "msmq-queue" } });
Defensive patterns

Strategy: validation

Validate before calling

static string[] ResolveSingleProviderQueues(JobStorage storage, IEnumerable<string> queues)
{
    var providers = queues.Select(q => storage.QueueProviders.GetProvider(q)).Distinct().ToArray();
    if (providers.Length != 1)
        throw new InvalidOperationException(
            "Queues span multiple providers; split them across separate server instances.");
    return queues.ToArray();
}

Prevention

When it happens

Trigger: Configuring a BackgroundJobServer (or calling FetchNextJob) with a queues array that spans providers registered in JobStorage.Current.QueueProviders — e.g. mixing "default" (Sql) with an MSMQ-backed queue name.

Common situations: Enabling UseMsmqQueues for some queues while keeping SQL queues and then listing both in BackgroundJobServerOptions.Queues; misconfiguring queue names so they resolve to different providers; running multiple server instances with overlapping but inconsistent queue sets.

Related errors


AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13). Data as JSON: /api/errors/484e58e2ddfb5480. Report an issue: GitHub.