dotnet/maui · error · ArgumentNullException

oldElement

Error message

oldElement

What it means

RendererPool is an obsolete (decorated with [System.Obsolete]) pool that recycles iOS child renderers when a parent VisualElement's element is swapped. Its constructor requires both a non-null renderer and a non-null oldElement; oldElement is later dereferenced as _oldElement in UpdateNewElement (line 56: ((IElementController)_oldElement).LogicalChildren). Passing null for oldElement would cause a NullReferenceException deep inside the swap logic, so the constructor fails fast with ArgumentNullException instead.

Source

Thrown at src/Compatibility/Core/src/iOS/RendererPool.cs:27

#endif
{
	[System.Obsolete]
	public sealed class RendererPool
	{
		readonly Dictionary<Type, Stack<IVisualElementRenderer>> _freeRenderers =
			new Dictionary<Type, Stack<IVisualElementRenderer>>();

		readonly VisualElement _oldElement;

		readonly IVisualElementRenderer _parent;

		public RendererPool(IVisualElementRenderer renderer, VisualElement oldElement)
		{
			if (renderer == null)
				throw new ArgumentNullException("renderer");

			if (oldElement == null)
				throw new ArgumentNullException("oldElement");

			_oldElement = oldElement;
			_parent = renderer;
		}

		public IVisualElementRenderer GetFreeRenderer(VisualElement view)
		{
			if (view == null)
				throw new ArgumentNullException("view");

			var rendererType = Controls.Internals.Registrar.Registered.GetHandlerTypeForObject(view) ?? typeof(ViewRenderer);

			Stack<IVisualElementRenderer> renderers;
			if (!_freeRenderers.TryGetValue(rendererType, out renderers) || renderers.Count == 0)
				return null;

			var renderer = renderers.Pop();
			renderer.SetElement(view);

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Ensure the VisualElement you pass as oldElement is non-null before constructing the pool (guard with 'if (oldElement == null) return;' or supply the parent's current Element).
  2. Avoid RendererPool entirely - it is marked [Obsolete]; prefer the modern MAUI handler/redirector pattern for renderer recycling.
  3. If you subclass a renderer that builds a RendererPool, check that base.Element is set before calling into the pool path.

Example fix

// before
var pool = new RendererPool(this, _oldElementReference); // _oldElementReference may be null

// after
if (_oldElementReference == null) return;
var pool = new RendererPool(this, _oldElementReference);
Defensive patterns

Strategy: validation

Validate before calling

if (oldElement == null) throw new ArgumentNullException(nameof(oldElement));
// or simply skip pool creation:
if (oldElement == null || renderer == null) return;
var pool = new RendererPool(renderer, oldElement);

Prevention

When it happens

Trigger: Constructing a new RendererPool(renderer, oldElement) where oldElement is null. This typically happens when a container renderer is initialised before its old element reference has been resolved, or when a caller passes the result of a GetRenderer() lookup that returned null.

Common situations: Migrating away from the Compatibility layer to the new MAUI handlers; custom renderers that manage their own pool; scenarios where the element is detached/disposed between the lookup and pool construction.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/87332c34f4be935b. Report an issue: GitHub.