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

  1. Do not assign null; if you want the default behavior, leave the property untouched (the constructor already calls GetDefaultSqlClientFactory()).
  2. Assign a concrete factory: Microsoft.Data.SqlClient.SqlClientFactory.Instance or System.Data.SqlClient.SqlClientFactory.Instance.
  3. Create a fresh SqlServerStorageOptions instance instead of resetting the factory on an existing one.
  4. 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

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.