HangfireIO/Hangfire · error · ArgumentNullException
value
Error message
value
What it means
ArgumentNullException thrown by the setter of the SqlServerStorageOptions.SqlClientFactory property (SqlServerStorageOptions.cs:202) when it is assigned null. The backing field _sqlClientFactory holds the DbProviderFactory used to create SqlConnection instances; assigning null is explicitly rejected. Note the getter is a separate failure mode: it throws InvalidOperationException if no default client factory was detected, but this particular error is the setter rejecting a null assignment.
Source
Thrown at src/Hangfire.SqlServer/SqlServerStorageOptions.cs:202
/// <summary>
/// Gets or sets whether to enable experimental feature of transactional acknowledge of completed
/// background jobs. In this case there will be less requests sent to SQL Server and better handling
/// of data loss when asynchronous replication is used. But additional blocking on the JobQueue table
/// is expected, since transaction commit requires an explicit Commit request to be sent.
/// </summary>
public bool UseTransactionalAcknowledge { get; set; }
/// <summary>
/// Gets or sets the <see cref="DbProviderFactory"/> for creating <c>SqlConnection</c> instances.
/// Defaults to either <c>System.Data.SqlClient.SqlClientFactory.Instance</c> or
/// <c>Microsoft.Data.SqlClient.SqlClientFactory</c> depending on which package reference exists
/// on the consuming project.
/// </summary>
public DbProviderFactory SqlClientFactory
{
get => _sqlClientFactory ?? throw new InvalidOperationException("Please add a NuGet package reference to either 'Microsoft.Data.SqlClient' or 'System.Data.SqlClient' in your application project. " +
"Hangfire.SqlServer supports both providers but let the consumer decide which one should be used.");
set => _sqlClientFactory = value ?? throw new ArgumentNullException(nameof(value));
}
/// <summary>
/// Gets or sets whether to try automatically query for the current schema on application start
/// and enable <see cref="UseIgnoreDupKeyOption"/>, <see cref="DeleteExpiredBatchSize"/> and
/// <see cref="DisableGlobalLocks"/> options depending on the current schema version. When storage
/// is inaccessible on startup, default values will be used for those options.
/// </summary>
public bool TryAutoDetectSchemaDependentOptions { get; set; }
/// <summary>
/// Gets or sets a default queue provider that will be used when no special provider was
/// registered for a particular queue.
/// </summary>
public IPersistentJobQueueProvider DefaultQueueProvider { get; set; }
#if FEATURE_TRANSACTIONSCOPE
/// <summary>View on GitHub (pinned to c236dd0f93)
Solutions
- Do not assign null; if you want the default behavior, leave the property untouched (the constructor already calls GetDefaultSqlClientFactory()).
- Assign a concrete factory: Microsoft.Data.SqlClient.SqlClientFactory.Instance or System.Data.SqlClient.SqlClientFactory.Instance.
- Create a fresh SqlServerStorageOptions instance instead of resetting the factory on an existing one.
- Fix the conditional logic so the branch never yields null, e.g. only assign when the provider value is non-null.
Example fix
// before options.SqlClientFactory = GetCurrentProvider(); // returns null in some path // after var factory = GetCurrentProvider(); if (factory != null) options.SqlClientFactory = factory; // or, to set explicitly: options.SqlClientFactory = Microsoft.Data.SqlClient.SqlClientFactory.Instance;
Defensive patterns
Strategy: validation
Validate before calling
var factory = ResolveSqlClientFactory();
if (factory != null)
{
options.SqlClientFactory = factory;
}
// never assign null; leave default if no explicit provider is chosen Prevention
- Never assign null to SqlClientFactory; leave the constructor's default if unsure.
- Resolve the provider once at startup and assign a concrete factory instance (Microsoft.Data.SqlClient.SqlClientFactory.Instance or System.Data.SqlClient.SqlClientFactory.Instance).
- Ensure configuration-binding/DI maps missing settings to a real factory, not null.
- To 'reset', create a new SqlServerStorageOptions rather than nulling the property.
When it happens
Trigger: Executing `options.SqlClientFactory = null;` on a SqlServerStorageOptions instance. This happens with a direct null assignment, a conditional expression that evaluates to null (e.g. `options.SqlClientFactory = provider ?? null;`), or a reset routine that clears the provider.
Common situations: Attempt to 'reset' the SQL client provider at runtime; a provider-selection block whose fallback branch is null; DI/configuration binding that maps a missing setting to null; test teardown that nulls the factory.
Related errors
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/7dc6203691e6474b.
Report an issue: GitHub.