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
- 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).
- Avoid RendererPool entirely - it is marked [Obsolete]; prefer the modern MAUI handler/redirector pattern for renderer recycling.
- 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
- Treat RendererPool as obsolete; prefer MAUI handlers.
- Null-check both constructor arguments before instantiating.
- Ensure the parent renderer's Element is attached before building a pool.
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.