HangfireIO/Hangfire · error · TypeLoadException
Could not load type 'SqlCommandSet' from assembly '{sqlClien
Error message
Could not load type 'SqlCommandSet' from assembly '{sqlClientAssembly}'. What it means
TypeLoadException thrown by SqlCommandSet's type loader when no public/internal type named 'SqlCommandSet' can be found in the resolved sqlClient assembly via GetTypes().FirstOrDefault. This means the provider assembly either does not expose batch-command infrastructure at all or its layout differs from what Hangfire expects.
Source
Thrown at src/Hangfire.SqlServer/SqlCommandSet.cs:70
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();
});
_setTransaction = SetTransaction.GetOrAdd(sqlCommandSetType, static type =>
{
var p = Expression.Parameter(typeof(object));
var converted = Expression.Convert(p, type);
var transactionParameter = Expression.Parameter(typeof(DbTransaction));View on GitHub (pinned to c236dd0f93)
Solutions
- Use a supported Microsoft.Data.SqlClient / System.Data.SqlClient version that exposes the SqlCommandSet type Hangfire expects.
- If using a custom/in-memory DbConnection in tests, disable batch inserts or provide a real provider connection.
- Update Hangfire.SqlServer to a version compatible with your provider's type layout.
Example fix
// before (test using a fake DbConnection) using var conn = new FakeDbConnection(); // after (use the real provider) using var conn = new SqlConnection(connectionString);
Defensive patterns
Strategy: type-guard
Validate before calling
static bool HasSqlCommandSetType(DbConnection connection)
=> connection.GetType().Assembly.GetTypes().Any(t => t.Name == "SqlCommandSet"); Type guard
static bool SupportsBatchCommands(DbConnection connection) =>
connection.GetType().Assembly.GetTypes().Any(static t => t.Name == "SqlCommandSet"); Prevention
- Use a supported SqlClient version; avoid custom/fake DbConnection in non-test code.
- Keep Hangfire.SqlServer and SqlClient versions aligned per release notes.
- Guard test fixtures so they skip batch-path tests when the provider lacks the type.
When it happens
Trigger: Pointing Hangfire.SqlServer at a connection whose underlying provider assembly has no SqlCommandSet type (e.g. Microsoft.Data.SqlClient on a platform/version where the internal type was renamed, or a third-party provider).
Common situations: Switching from System.Data.SqlClient to Microsoft.Data.SqlClient where the batch type isn't located; using a provider stub or mocked DbConnection in tests; provider version that reorganized internal types.
Related errors
- Property '{type.FullName}.Connection' not found.
- Property '{type.FullName}.Transaction' not found.
- Property '{type.FullName}.BatchCommand' not found.
- SqlCommandSet for {connection.GetType().FullName} is not sup
- Only public methods can be invoked in the background. Ensure
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/a351a64fc42a7ddf.
Report an issue: GitHub.