{"record":{"id":"d6e879ef2e23d834","repo":"AvaloniaUI/Avalonia","slug":"surfaceview-holder-was-not-expected-to-be-null-dur","errorCode":null,"errorMessage":"SurfaceView.Holder was not expected to be null during InvalidationAwareSurfaceView initialization.","messagePattern":"SurfaceView\\.Holder was not expected to be null during InvalidationAwareSurfaceView initialization\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs","lineNumber":32,"sourceCode":"    internal abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback2, INativePlatformHandleSurface\n    {\n        private IntPtr _nativeWindowHandle = IntPtr.Zero;\n        private PixelSize _size = new(1, 1);\n        private double _scaling = 1;\n\n        public event EventHandler? SurfaceWindowCreated;\n        public event EventHandler? SurfaceWindowDestroyed;\n\n        public PixelSize Size => _size;\n        public double Scaling => _scaling;\n\n        IntPtr IPlatformHandle.Handle => _nativeWindowHandle;\n        string IPlatformHandle.HandleDescriptor => \"SurfaceView\";\n\n        protected InvalidationAwareSurfaceView(Context context) : base(context)\n        {\n            if (Holder is null)\n                throw new InvalidOperationException(\n                    \"SurfaceView.Holder was not expected to be null during InvalidationAwareSurfaceView initialization.\");\n\n            Holder.AddCallback(this);\n            Holder.SetFormat(global::Android.Graphics.Format.Transparent);\n        }\n\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing)\n                Holder?.RemoveCallback(this);\n\n            ReleaseNativeWindowHandle();\n            base.Dispose(disposing);\n        }\n\n        public virtual void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)\n        {\n            Logger.TryGet(LogEventLevel.Verbose, LogArea.AndroidPlatform)?","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs#L14-L50","documentation":"Thrown by the InvalidationAwareSurfaceView base constructor when the inherited SurfaceView.Holder is null at construction time. Per the Android framework, SurfaceView.getHolder() should never be null after super(context) completes, so this guard exists to fail fast on a broken/edge-case Context or a non-standard construction path.","triggerScenarios":"Constructing an InvalidationAwareSurfaceView subclass with a Context that does not properly initialize the View infrastructure, or constructing it before the framework attaches a window. Most realistically hit by instantiating the view with an invalid Context (e.g. a stripped/mock context, or during unit tests without a real Android view stack).","commonSituations":"Running instrumentation/unit tests that construct the view with a mock Context; passing a ContextWrapper that delegates incorrectly; using the view in a non-standard host (e.g. Flutter plugin interop) where the SurfaceView base behavior is overridden; AndroidX/fragment framework version mismatches that alter Holder initialization timing.","solutions":["Always construct InvalidationAwareSurfaceView subclasses with a real, fully functional Context (the host Activity or a ContextThemeWrapper over it).","In tests, use a Robolectric or instrumentation runner that provides a working view infrastructure rather than a bare mock Context.","Verify the AndroidX fragment/appcompat libraries are at supported versions; a mismatch can alter View initialization ordering.","Do not bypass the base SurfaceView lifecycle — let super(context) run normally before any custom init."],"exampleFix":"// before — context is a stripped mock\nvar view = new SurfaceViewImpl(mockContext, topLevel, false);\n\n// after — use the real activity context\nvar view = new SurfaceViewImpl(activityContext, topLevel, false);","handlingStrategy":"validation","validationCode":"// ensure a real, fully functional Context is passed before constructing the view\nif (context is null || !IsRealContext(context))\n    throw new InvalidOperationException(\"A real Activity context is required.\");\nvar view = new SurfaceViewImpl(context, topLevel, placeOnTop);","typeGuard":"static bool IsRealContext(Context? c) => c is Android.App.Activity or ContextWrapper;","tryCatchPattern":null,"preventionTips":["Always construct surface views with the host Activity (or a ContextThemeWrapper over it).","In tests, use Robolectric/instrumentation context, not a bare mock.","Keep AndroidX/fragment library versions consistent to preserve View init ordering.","Do not subclass-constrain the SurfaceView base constructor."],"tags":["android","surface","construction","context","lifecycle"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}