{"record":{"id":"9f014ce77f73ee87","repo":"dotnet/machinelearning","slug":"predictionenginepool-2","errorCode":null,"errorMessage":"PredictionEnginePool`2","messagePattern":"PredictionEnginePool`2","errorType":"exception","errorClass":"ObjectDisposedException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.Extensions.ML/PredictionEnginePool.cs","lineNumber":92,"sourceCode":"        /// </summary>\n        public PredictionEngine<TData, TPrediction> GetPredictionEngine()\n        {\n            return GetPredictionEngine(string.Empty);\n        }\n\n        /// <summary>\n        /// Gets a PredictionEngine for a named model.\n        /// </summary>\n        /// <param name=\"modelName\">\n        /// The name of the model which allows for uniquely identifying the model when\n        /// multiple models have the same <typeparamref name=\"TData\"/> and\n        /// <typeparamref name=\"TPrediction\"/> types.\n        /// </param>\n        public PredictionEngine<TData, TPrediction> GetPredictionEngine(string modelName)\n        {\n            if (Volatile.Read(ref _disposed) != 0)\n            {\n                throw new ObjectDisposedException(nameof(PredictionEnginePool<TData, TPrediction>));\n            }\n\n            if (_namedPools.TryGetValue(modelName, out var existingPool))\n            {\n                return existingPool.Get();\n            }\n\n            //This is the case where someone has used string.Empty to get the default model.\n            //We can throw all the time, but it seems reasonable that we would just do what\n            //they are expecting if they know that an empty string means default.\n            if (string.IsNullOrEmpty(modelName))\n            {\n                if (_defaultEnginePool == null)\n                {\n                    throw new ArgumentException(\"You need to configure a default, not named, model before you use this method.\");\n                }\n\n                return _defaultEnginePool.Get();","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.Extensions.ML/PredictionEnginePool.cs#L74-L110","documentation":"PredictionEnginePool.GetPredictionEngine(modelName) checks _disposed before returning a pooled engine; after Dispose() (host shutdown or hot-swap) it throws ObjectDisposedException named PredictionEnginePool<TData,TPrediction>.","triggerScenarios":"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.","commonSituations":"Singleton-captured pool used by a background thread after host shutdown; long-running prediction loops surviving a model hot-swap that disposes old pools.","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"],"exampleFix":"// before\n_pool.GetPredictionEngine(\"modelA\"); // stale reference\n// after\nusing var scope = _scopeFactory.CreateScope();\nvar pool = scope.ServiceProvider.GetRequiredService<PredictionEnginePool<MData,Pred>>();\npool.GetPredictionEngine(\"modelA\");","handlingStrategy":"try-catch","validationCode":"// resolve pool via IServiceProvider right before use instead of holding a reference","typeGuard":"null","tryCatchPattern":"try { var e = pool.GetPredictionEngine(\"m\"); } catch (ObjectDisposedException) { pool = sp.GetRequiredService<PredictionEnginePool<TData,TPred>>(); var e = pool.GetPredictionEngine(\"m\"); }","preventionTips":["Use IHostApplicationLifetime to stop prediction work before dispose","Re-resolve pools per scope","Avoid using the pool after app shutdown begins"],"tags":["object-disposed","pooling","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}