dotnet/machinelearning · error · ArgumentNullException

engine (Parameter 'engine')

Error message

engine (Parameter 'engine')

What it means

ArgumentNullException in PoolLoader<TData,TPrediction>.Return: the engine parameter is null. Return must put a previously rented PredictionEngine back into its originating pool (or dispose it if that generation was hot-swapped), so a null reference cannot be identified with any rental and is rejected immediately. The message names 'engine' as the faulty parameter.

Solutions

  1. Guard for null before calling Return
  2. Only return engines that were successfully rented from Get()

Example fix

// before
pool.ReturnPredictionEngine(engine); // engine may be null
// after
if (engine != null) pool.ReturnPredictionEngine(engine);
Defensive patterns

Strategy: type-guard

Validate before calling

if (engine is null) throw new InvalidOperationException("No engine to return");

Type guard

bool CanReturn(PredictionEngine<TData,TPred> e) => e != null;

Try / catch

null // prevent by null-checking before Return; no need to catch ArgumentNullException

Prevention

When it happens

Trigger: Calling ReturnPredictionEngine / PoolLoader.Return(null), typically when a variable was never assigned or a Get() failed earlier.

Common situations: Code paths where engine creation failed but Return is still called in a finally block without a null check.

Related errors


AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11). Data as JSON: /api/errors/a01e0525ca06126f. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.Extensions.ML/PoolLoader.cs:83

                throw new ObjectDisposedException(nameof(PoolLoader<TData, TPrediction>));
            }

            var engine = pool.Get();

            _rentedEngines.Remove(engine);
            _rentedEngines.Add(engine, pool);
            return engine;
        }

        /// <summary>
        /// Returns an engine to the generation it was rented from. If that generation has already
        /// been disposed by a hot-swap, the pool disposes the engine instead of retaining it.
        /// </summary>
        public void Return(PredictionEngine<TData, TPrediction> engine)
        {
            if (engine == null)
            {
                throw new ArgumentNullException(nameof(engine));
            }

            if (_rentedEngines.TryGetValue(engine, out var origin))
            {
                _rentedEngines.Remove(engine);
                origin.Return(engine);
            }
            else
            {
                engine.Dispose();
            }
        }

        private void LoadPool()
        {
            if (Volatile.Read(ref _disposed) != 0)
            {
                return;

View on GitHub (pinned to 7b76e69cf9)