dotnet/reactive · critical · NotSupportedException
The scheduler service
Error message
The scheduler service '{0}' is not available. What it means
Scheduler.Initialize resolves an IScheduler from the platform enlightenment provider by service name; when the provider returns no implementation it throws NotSupportedException with 'The scheduler service "{0}" is not available.' This is how Scheduler.ThreadPool, NewThread and TaskPool lazily bind to the platform at first access.
Solutions
- Reference System.Reactive.PlatformServices so the default provider registers scheduler services
- If using a custom PlatformEnlightenmentProvider, ensure GetService<IScheduler>(name) returns implementations for "ThreadPool", "NewThread", "TaskPool"
- Use Scheduler.Default / immediate schedulers as a fallback instead of the missing service
Example fix
// before
class MyProvider : IPlatformEnlightenmentProvider
{
public T GetService<T>(object[] args) where T : class => null; // scheduler services missing
}
// after
public T GetService<T>(object[] args) where T : class
{
if (typeof(T) == typeof(IScheduler)) return new MyScheduler() as T;
return new DefaultPlatformEnlightenmentProvider().GetService<T>(args);
} Defensive patterns
Strategy: fallback
Validate before calling
var sched = PlatformEnlightenmentProvider.Current.GetService<IScheduler>("ThreadPool");
if (sched == null) sched = new DefaultSchedulerShim(); Type guard
static bool SchedulerServiceAvailable<T>() where T : class => PlatformEnlightenmentProvider.Current.GetService<T>("ThreadPool") != null; Try / catch
try { sched = Scheduler.TaskPool; }
catch (NotSupportedException ex)
{
// fall back to default scheduler or log environment misconfiguration
sched = Scheduler.Default;
} Prevention
- Always reference System.Reactive.PlatformServices in executable projects
- Test first access to Scheduler.ThreadPool/TaskPool in your host environment
- When replacing IPlatformEnlightenmentProvider, delegate unknown services to the default provider
When it happens
Trigger: Accessing Scheduler.ThreadPool, Scheduler.NewThread or Scheduler.TaskPool in an environment where the platform enlightenment provider was not configured (e.g. custom PlatformEnlightenmentProvider without scheduler services, trimmed/AOT app missing the System.Reactive.PlatformServices registration).
Common situations: Replacing the default enlightenment provider with a custom one that omits IScheduler services; unit-test hosts that stub the provider; missing platform services package in some targets.
Related errors
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/1967516b01127a7b.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Concurrency/Scheduler.cs:90
/// <summary>
/// Gets a scheduler that schedules work on a new thread using default thread creation options.
/// </summary>
[Obsolete(Constants_Core.ObsoleteSchedulerNewthread)]
public static IScheduler NewThread => _newThread.Value;
private static readonly Lazy<IScheduler> _taskPool = new(static () => Initialize("TaskPool"));
/// <summary>
/// Gets a scheduler that schedules work on Task Parallel Library (TPL) task pool using the default TaskScheduler.
/// </summary>
[Obsolete(Constants_Core.ObsoleteSchedulerTaskpool)]
public static IScheduler TaskPool => _taskPool.Value;
private static IScheduler Initialize(string name)
{
return PlatformEnlightenmentProvider.Current.GetService<IScheduler>(name)
?? throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings_Core.CANT_OBTAIN_SCHEDULER, name));
}
}
}
View on GitHub (pinned to 94b5d5ab91)