dotnet/machinelearning · error · ObjectDisposedException
PredictionEnginePool`2
Error message
PredictionEnginePool`2
What it means
PredictionEnginePool.GetPredictionEngine(modelName) checks _disposed before returning a pooled engine; after Dispose() (host shutdown or hot-swap) it throws ObjectDisposedException named PredictionEnginePool<TData,TPrediction>.
Solutions
- Re-resolve the pool from the service provider for each prediction batch
- Catch ObjectDisposedException and rebuild/resolve a new pool
- Ensure prediction work is cancelled during host shutdown
Example fix
// before
_pool.GetPredictionEngine("modelA"); // stale reference
// after
using var scope = _scopeFactory.CreateScope();
var pool = scope.ServiceProvider.GetRequiredService<PredictionEnginePool<MData,Pred>>();
pool.GetPredictionEngine("modelA"); Defensive patterns
Strategy: try-catch
Validate before calling
// resolve pool via IServiceProvider right before use instead of holding a reference
Type guard
null
Try / catch
try { var e = pool.GetPredictionEngine("m"); } catch (ObjectDisposedException) { pool = sp.GetRequiredService<PredictionEnginePool<TData,TPred>>(); var e = pool.GetPredictionEngine("m"); } Prevention
- Use IHostApplicationLifetime to stop prediction work before dispose
- Re-resolve pools per scope
- Avoid using the pool after app shutdown begins
When it happens
Trigger: Calling GetPredictionEngine after the pool instance was disposed — e.g. holding a stale reference across a model update or using the pool after the DI scope/host was torn down.
Common situations: Singleton-captured pool used by a background thread after host shutdown; long-running prediction loops surviving a model hot-swap that disposes old pools.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- PoolLoader`1
- engine (Parameter 'engine')
- engine (Parameter 'engine')
- Object is disposed.
- Start must be called on a ModelLoader before it can be used.
AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11).
Data as JSON: /api/errors/9f014ce77f73ee87.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.Extensions.ML/PredictionEnginePool.cs:92
/// </summary>
public PredictionEngine<TData, TPrediction> GetPredictionEngine()
{
return GetPredictionEngine(string.Empty);
}
/// <summary>
/// Gets a PredictionEngine for a named model.
/// </summary>
/// <param name="modelName">
/// The name of the model which allows for uniquely identifying the model when
/// multiple models have the same <typeparamref name="TData"/> and
/// <typeparamref name="TPrediction"/> types.
/// </param>
public PredictionEngine<TData, TPrediction> GetPredictionEngine(string modelName)
{
if (Volatile.Read(ref _disposed) != 0)
{
throw new ObjectDisposedException(nameof(PredictionEnginePool<TData, TPrediction>));
}
if (_namedPools.TryGetValue(modelName, out var existingPool))
{
return existingPool.Get();
}
//This is the case where someone has used string.Empty to get the default model.
//We can throw all the time, but it seems reasonable that we would just do what
//they are expecting if they know that an empty string means default.
if (string.IsNullOrEmpty(modelName))
{
if (_defaultEnginePool == null)
{
throw new ArgumentException("You need to configure a default, not named, model before you use this method.");
}
return _defaultEnginePool.Get();View on GitHub (pinned to 7b76e69cf9)