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
- Give each BackgroundJobServer a queues array that resolves to exactly one provider, and split mixed workloads across separate server instances.
- Review QueueProviders registrations and the queues array to ensure all entries map to the same provider.
- 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
- Run each BackgroundJobServer with queues from exactly one provider.
- Audit QueueProviders registrations whenever you add MSMQ or other providers.
- Add a startup check that all configured queues resolve to a single provider.
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
- Timeout value should be equal to or greater than zero.
- Attempts value must be equal or greater than zero.
- DelaysInSeconds value must be an array of non-negative numbe
- client
- storage
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/484e58e2ddfb5480.
Report an issue: GitHub.