{"record":{"id":"38bc9cddefd339aa","repo":"dotnet/maui","slug":"renderer-38bc9c","errorCode":null,"errorMessage":"renderer","messagePattern":"renderer","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs","lineNumber":40,"sourceCode":"\t\tButton _element;\n\t\tbool _preserveInitialPadding;\n\t\tbool _spacingAdjustsPadding;\n\t\tbool _borderAdjustsPadding;\n\t\tbool _collapseHorizontalPadding;\n\n\t\tUIEdgeInsets? _defaultImageInsets;\n\t\tUIEdgeInsets? _defaultTitleInsets;\n\t\tUIEdgeInsets? _defaultContentInsets;\n\n\t\tUIEdgeInsets _paddingAdjustments = new UIEdgeInsets();\n\n\t\tpublic ButtonLayoutManager(IButtonLayoutRenderer renderer,\n\t\t\tbool preserveInitialPadding = false,\n\t\t\tbool spacingAdjustsPadding = true,\n\t\t\tbool borderAdjustsPadding = false,\n\t\t\tbool collapseHorizontalPadding = false)\n\t\t{\n\t\t\t_renderer = renderer ?? throw new ArgumentNullException(nameof(renderer));\n\t\t\t_renderer.ElementChanged += OnElementChanged;\n\t\t\t_preserveInitialPadding = preserveInitialPadding;\n\t\t\t_spacingAdjustsPadding = spacingAdjustsPadding;\n\t\t\t_borderAdjustsPadding = borderAdjustsPadding;\n\t\t\t_collapseHorizontalPadding = collapseHorizontalPadding;\n\n\t\t\tImageElementManager.Init(renderer.ImageVisualElementRenderer);\n\t\t}\n\n\t\tUIButton Control => _renderer?.Control;\n\n\t\tIImageVisualElementRenderer ImageVisualElementRenderer => _renderer?.ImageVisualElementRenderer;\n\n\t\tpublic void Dispose()\n\t\t{\n\t\t\tDispose(true);\n\t\t}\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs#L22-L58","documentation":"ButtonLayoutManager is a helper that manages spacing/padding/insets for a UIButton-backed control (Button, ImageButton). Its constructor stores the renderer, subscribes to ElementChanged, and calls ImageElementManager.Init on the renderer's image renderer (line 52). A null renderer would NPE immediately, so it is rejected up front.","triggerScenarios":"Constructing new ButtonLayoutManager(null) - typically a ButtonRenderer/ImageButtonRenderer that passes 'this' before it is fully constructed, or a null due to a dependency-injection/custom-renderer override returning null.","commonSituations":"Custom Button/ImageButton renderers that instantiate ButtonLayoutManager in a field initializer or before the base renderer is assigned; incorrect hand-rolled renderer wiring.","solutions":["Construct ButtonLayoutManager inside the renderer's constructor body (after base/init) where 'this' is a valid non-null IButtonLayoutRenderer.","Ensure your custom renderer actually implements IButtonLayoutRenderer before passing it.","Pass explicit preserve/spacing flags rather than relying on defaults that assume a live renderer."],"exampleFix":"// before\nprivate ButtonLayoutManager _layout = new ButtonLayoutManager(this);\n\n// after\nprivate ButtonLayoutManager _layout;\npublic MyButtonRenderer() { _layout = new ButtonLayoutManager(this); }","handlingStrategy":"validation","validationCode":"if (renderer == null) throw new ArgumentNullException(nameof(renderer));\nvar mgr = new ButtonLayoutManager(renderer);","typeGuard":"static bool IsButtonLayoutRenderer(object r) => r is IButtonLayoutRenderer;","tryCatchPattern":null,"preventionTips":["Construct ButtonLayoutManager only after base renderer is initialised.","Confirm the renderer implements IButtonLayoutRenderer."],"tags":["argumentnullexception","ios","button-layout","renderer-wiring"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}