microsoft/garnet · error · Exception
Unable to call ThreadPool.SetMinThreads with
Error message
Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads} What it means
Thrown by GarnetServer.InitializeServer when ThreadPool.SetMinThreads returns false after the user configured ThreadPoolMinThreads or ThreadPoolMinIOCompletionThreads to non-zero values. The CLR rejects min thread values that exceed the current max thread limits, or are otherwise invalid. The error message includes the attempted values for diagnosis.
Solutions
- Ensure ThreadPoolMinThreads <= ThreadPoolMaxThreads and ThreadPoolMinIOCompletionThreads <= ThreadPoolMaxIOCompletionThreads.
- If setting min threads, also set max threads to equal or higher values.
- Reduce the min thread values to a valid range for your environment.
- Check container host resource limits that may constrain the thread pool.
Example fix
// before: min exceeds default max
var opts = new GarnetServerOptions
{
ThreadPoolMinThreads = 500 // but max is default (~32767 on most systems, or lower in containers)
};
// after: set both consistently
var opts = new GarnetServerOptions
{
ThreadPoolMinThreads = 200,
ThreadPoolMaxThreads = 500
}; Defensive patterns
Strategy: validation
Validate before calling
if (opts.ThreadPoolMinThreads > 0 || opts.ThreadPoolMinIOCompletionThreads > 0)
{
ThreadPool.GetMaxThreads(out var maxWorker, out var maxIO);
if (opts.ThreadPoolMinThreads > maxWorker)
throw new InvalidOperationException($"Min worker threads ({opts.ThreadPoolMinThreads}) exceeds max ({maxWorker})");
if (opts.ThreadPoolMinIOCompletionThreads > maxIO)
throw new InvalidOperationException($"Min IO threads ({opts.ThreadPoolMinIOCompletionThreads}) exceeds max ({maxIO})");
} Type guard
static bool AreMinThreadSettingsValid(GarnetServerOptions opts)
{
ThreadPool.GetMaxThreads(out var maxWorker, out var maxIO);
var minWorker = opts.ThreadPoolMinThreads > 0 ? opts.ThreadPoolMinThreads : 0;
var minIO = opts.ThreadPoolMinIOCompletionThreads > 0 ? opts.ThreadPoolMinIOCompletionThreads : 0;
return minWorker <= maxWorker && minIO <= maxIO;
} Prevention
- Always set max threads >= min threads when configuring the thread pool.
- Query current ThreadPool.GetMaxThreads before setting min values.
- Avoid overriding thread pool settings unless you have measured a specific need.
When it happens
Trigger: Setting --thread-pool-min-threads or --thread-pool-min-io-completion-threads to values that are higher than the current max thread counts, or otherwise rejected by the runtime. The CLR requires min <= max for both worker and completion port threads.
Common situations: Setting min threads higher than max threads; containerized environments where the host has restrictive thread limits; configuring min threads without also setting max threads to accommodate.
Related errors
- Unable to call ThreadPool.SetMaxThreads with
- AofMemorySize (effective after rounding down to a power of…
- AofPageSize (effective after rounding down to a power of…
- AofPageSize (effective after rounding down to a power of…
- Authentication mode is not supported.
AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13).
Data as JSON: /api/errors/7bf7893eca9a8333.
Report an issue: GitHub.
Appendix: source
Thrown at libs/host/GarnetServer.cs:237
minChanged = true;
}
if (opts.ThreadPoolMaxThreads > 0)
{
maxThreads = opts.ThreadPoolMaxThreads;
maxChanged = true;
}
if (opts.ThreadPoolMaxIOCompletionThreads > 0)
{
maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads;
maxChanged = true;
}
// First try to set the max threads
var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads);
// Set the min threads
if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads))
throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}");
// Retry to set max threads if it wasn't set in the earlier step
if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads))
throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}");
opts.Initialize(loggerFactory);
StoreWrapper.DatabaseCreatorDelegate createDatabaseDelegate = (int dbId) =>
CreateDatabase(dbId, opts, clusterFactory, customCommandManager);
if (!opts.DisablePubSub)
subscribeBroker = new SubscribeBroker(null, opts.PubSubPageSizeBytes(), pubSubEpoch, startFresh: true, logger);
logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled");
// Create Garnet TCP server if none was provided.
if (servers == null)
{
servers = new IGarnetServer[opts.EndPoints.Length];View on GitHub (pinned to 951b0fc683)