HangfireIO/Hangfire · error · NotSupportedException
.NET Core version of the System.Data.SqlClient package below
Error message
.NET Core version of the System.Data.SqlClient package below 4.7.0 (which has assembly version 4.6.0.0) doesn't properly implement the SqlCommandSet class.
What it means
NotSupportedException thrown by SqlCommandSet's lazy type loader when the resolved sqlClientAssembly is named 'System.Data.SqlClient' and its assembly version is greater than 4.0.0.0 but less than 4.6.0.0. Those .NET Core package versions (< 4.7.0 NuGet, assembly 4.6.0.0) ship a broken SqlCommandSet that throws 'Specified parameter name is not valid' at runtime (corefx #29391), so Hangfire refuses to use batch commands on them.
Source
Thrown at src/Hangfire.SqlServer/SqlCommandSet.cs:64
public SqlCommandSet(DbConnection connection)
{
Type sqlCommandSetType;
try
{
sqlCommandSetType = SqlCommandSetType.GetOrAdd(connection.GetType().GetTypeInfo().Assembly, static sqlClientAssembly =>
{
var assemblyName = sqlClientAssembly.GetName();
var version = assemblyName.Version;
if (assemblyName.Name == "System.Data.SqlClient" && Version.Parse("4.0.0.0") < version && version < Version.Parse("4.6.0.0"))
{
// .NET Core version of the System.Data.SqlClient package below 4.7.0 (which
// has assembly version 4.6.0.0) doesn't properly implement the SqlCommandSet
// class, throwing the following exception in run-time:
// ArgumentException: Specified parameter name 'Parameter1' is not valid.
// GitHub Issue: https://github.com/dotnet/corefx/issues/29391
throw new NotSupportedException(".NET Core version of the System.Data.SqlClient package below 4.7.0 (which has assembly version 4.6.0.0) doesn't properly implement the SqlCommandSet class.");
}
var type = sqlClientAssembly.GetTypes().FirstOrDefault(static x => x.Name == "SqlCommandSet");
if (type == null)
{
throw new TypeLoadException($"Could not load type 'SqlCommandSet' from assembly '{sqlClientAssembly}'.");
}
return type;
});
_setConnection = SetConnection.GetOrAdd(sqlCommandSetType, static type =>
{
var p = Expression.Parameter(typeof(object));
var converted = Expression.Convert(p, type);
var connectionParameter = Expression.Parameter(typeof(DbConnection));
var connectionProperty = type.GetProperty("Connection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new MissingMemberException($"Property '{type.FullName}.Connection' not found.");
return Expression.Lambda<Action<object, DbConnection>>(Expression.Assign(Expression.Property(converted, connectionProperty), Expression.Convert(connectionParameter, connectionProperty.PropertyType)), p, connectionParameter).Compile();View on GitHub (pinned to c236dd0f93)
Solutions
- Upgrade the System.Data.SqlClient NuGet package to 4.7.0 or later (ideally the newest 4.8.x).
- Switch to Microsoft.Data.SqlClient which does not hit this assembly-version range.
- Run dotnet list package --outdated and pin a minimum version in your .csproj to prevent downgrade.
Example fix
// before <PackageReference Include="System.Data.SqlClient" Version="4.6.1" /> // after <PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
Defensive patterns
Strategy: validation
Validate before calling
// build-time check
var asm = typeof(SqlConnection).Assembly.GetName();
if (asm.Name == "System.Data.SqlClient"
&& Version.Parse("4.0.0.0") < asm.Version && asm.Version < Version.Parse("4.6.0.0"))
throw new InvalidOperationException("Upgrade System.Data.SqlClient to >= 4.7.0."); Try / catch
try { /* batch insert path */ }
catch (NotSupportedException ex) when (ex.Message.Contains("SqlCommandSet"))
{
// fall back to regular, non-batched command execution
} Prevention
- Pin System.Data.SqlClient to >= 4.8.x in Directory.Packages.props.
- Prefer Microsoft.Data.SqlClient for new projects.
- Run dotnet list package --outdated in CI.
When it happens
Trigger: Using Hangfire.SqlServer on .NET Core/5+ with the System.Data.SqlClient NuGet package pinned below 4.7.0 while Hangfire attempts to batch commands.
Common situations: Inheriting an older packages.lock or transitive dependency on System.Data.SqlClient < 4.7.0; CI restoring an old cached package; a transitive dependency forcing the older version.
Related errors
- SqlCommandSet for {connection.GetType().FullName} is not sup
- Current storage doesn't support specifying queues directly f
- Only public methods can be invoked in the background. Ensure
- Job method can not contain unassigned generic type parameter
- Global methods are not supported. Use class methods instead.
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/8a7b15794ada887c.
Report an issue: GitHub.