dotnet/maui · error · ArgumentNullException

renderer

Error message

renderer

What it means

RendererPool constructor throws ArgumentNullException("renderer") when the IVisualElementRenderer argument is null. RendererPool manages recycled renderers for a parent renderer and cannot operate without one; it also rejects null oldElement for the same reason.

Source

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

#else

namespace Microsoft.Maui.Controls.Compatibility.Platform.MacOS
#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;

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Construct RendererPool only after the renderer is non-null and initialized.
  2. Null-check both arguments before construction.
  3. Move RendererPool initialization to OnElementChanged (not the constructor).

Example fix

// before
_pool = new RendererPool(null, oldElement);
// after
if (renderer == null)
    throw new InvalidOperationException("Renderer not ready for RendererPool.");
_pool = new RendererPool(renderer, oldElement);
Defensive patterns

Strategy: validation

Validate before calling

if (renderer == null || oldElement == null)
    throw new InvalidOperationException("RendererPool requires non-null renderer and oldElement.");
var pool = new RendererPool(renderer, oldElement);

Type guard

static bool CanBuildPool(IVisualElementRenderer r, VisualElement oldE) => r != null && oldE != null;

Prevention

When it happens

Trigger: Constructing RendererPool with a null renderer; typically inside a custom layout renderer during OnElementChanged when the new renderer is not yet established.

Common situations: Custom renderers that build a RendererPool before Platform.GetRenderer returns a value; layout/renderers that recycle children and reference a null parent during teardown.

Related errors


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