{"record":{"id":"ad442644486ccd9e","repo":"dotnet/maui","slug":"newelement-ad4426","errorCode":null,"errorMessage":"newElement","messagePattern":"newElement","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Compatibility/Core/src/iOS/RendererPool.cs","lineNumber":52,"sourceCode":"\t\t{\n\t\t\tif (view == null)\n\t\t\t\tthrow new ArgumentNullException(\"view\");\n\n\t\t\tvar rendererType = Controls.Internals.Registrar.Registered.GetHandlerTypeForObject(view) ?? typeof(ViewRenderer);\n\n\t\t\tStack<IVisualElementRenderer> renderers;\n\t\t\tif (!_freeRenderers.TryGetValue(rendererType, out renderers) || renderers.Count == 0)\n\t\t\t\treturn null;\n\n\t\t\tvar renderer = renderers.Pop();\n\t\t\trenderer.SetElement(view);\n\t\t\treturn renderer;\n\t\t}\n\n\t\tpublic void UpdateNewElement(VisualElement newElement)\n\t\t{\n\t\t\tif (newElement == null)\n\t\t\t\tthrow new ArgumentNullException(\"newElement\");\n\n\t\t\tvar sameChildrenTypes = true;\n\n\t\t\tvar oldChildren = ((IElementController)_oldElement).LogicalChildren;\n\t\t\tvar oldNativeChildren = _parent.NativeView.Subviews;\n\t\t\tvar newChildren = ((IElementController)newElement).LogicalChildren;\n\n\t\t\tif (oldChildren.Count == newChildren.Count && oldNativeChildren.Length >= oldChildren.Count)\n\t\t\t{\n\t\t\t\tfor (var i = 0; i < oldChildren.Count; i++)\n\t\t\t\t{\n\t\t\t\t\tvar oldChildType = (oldNativeChildren[i] as IVisualElementRenderer)?.Element?.GetType();\n\t\t\t\t\tif (oldChildType != newChildren[i].GetType())\n\t\t\t\t\t{\n\t\t\t\t\t\tsameChildrenTypes = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Compatibility/Core/src/iOS/RendererPool.cs#L34-L70","documentation":"UpdateNewElement(VisualElement newElement) re-syncs the native subview tree when the parent's element is replaced. It immediately reads newElement's LogicalChildren (line 58) and compares them against _oldElement's children, so a null newElement would NPE during that diff. The guard rejects null before the diff.","triggerScenarios":"Calling pool.UpdateNewElement(null), which happens when the renderer's OnElementChanged receives a newElement that is null (element detached) and forwards it to the pool unconditionally.","commonSituations":"Element swap during disposal; a custom renderer forwarding e.NewElement to UpdateNewElement without checking the ElementChanged event semantics.","solutions":["Guard UpdateNewElement calls: only invoke it when e.NewElement is non-null (skip on detach).","In OnElementChanged, return early if args.NewElement == null rather than pooling.","Migrate off the obsolete RendererPool to handler-based recycling."],"exampleFix":"// before\n_pool.UpdateNewElement(e.NewElement);\n\n// after\nif (e.NewElement != null)\n    _pool.UpdateNewElement(e.NewElement);","handlingStrategy":"validation","validationCode":"if (e.NewElement == null) return;\n_pool.UpdateNewElement(e.NewElement);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never forward a null NewElement to UpdateNewElement.","Handle the detach case in OnElementChanged separately."],"tags":["argumentnullexception","ios","renderer-pool","element-changed"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}