{"record":{"id":"8fe2fe54853632cc","repo":"dotnet/wpf","slug":"sr-mediacontext-apinotallowed","errorCode":null,"errorMessage":"SR.MediaContext_APINotAllowed","messagePattern":"SR\\.MediaContext_APINotAllowed","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/MediaContext.cs","lineNumber":2298,"sourceCode":"\n        /// <summary>\n        /// This function is registered with the MediaContext's TimeManager. It is called whenever\n        /// a clock managed by the TimeManager goes active, but only if there hasn't been already an\n        /// active clock. For now we start the animation thread in there.\n        /// </summary>\n        private void OnNeedTickSooner(object sender, EventArgs e)\n        {\n            PostRender();\n        }\n\n        /// <summary>\n        /// Checks if the current context can request the specified permissions.\n        /// </summary>\n        internal void VerifyWriteAccess()\n        {\n            if (!WriteAccessEnabled)\n            {\n                throw new InvalidOperationException(SR.MediaContext_APINotAllowed);\n            }\n        }\n\n        /// <summary>\n        /// Returns false if the MediaContext is currently read-only\n        /// </summary>\n        internal bool WriteAccessEnabled\n        {\n            get { return _readOnlyAccessCounter <= 0; }\n        }\n\n        /// <summary>\n        /// Methods to lock down the Visual tree for write access.\n        /// </summary>\n        internal void PushReadOnlyAccess()\n        {\n            _readOnlyAccessCounter++;\n        }","sourceCodeStart":2280,"sourceCodeEnd":2316,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/MediaContext.cs#L2280-L2316","documentation":"MediaContext.VerifyWriteAccess throws InvalidOperationException(SR.MediaContext_APINotAllowed) when an API that mutates rendering state is called while the MediaContext is in read-only mode (WriteAccessEnabled == false). Certain APIs are forbidden in contexts like rendering during dispose or from disallowed threads/states.","triggerScenarios":"Calling a rendering API guarded by VerifyWriteAccess (e.g., modifying visuals or subscribing to rendering during teardown) after the MediaContext went read-only — commonly during window close / application shutdown while render callbacks still fire.","commonSituations":"CompositionTarget.Rendering handlers touching visuals after the host window is closed; background threads mutating visuals without Dispatcher dispatch; work scheduled in finalizers/shutdown hooks.","solutions":["Stop rendering work before shutdown: unsubscribe CompositionTarget.Rendering in Window.Closed/Unloaded.","Marshal visual mutations to the UI thread via Dispatcher.Invoke/BeginInvoke with DispatcherObject checks.","Guard callbacks with a disposed/closing flag and bail out early when the window is closing.","Delay resource-freeing work until after the render pass completes (Dispatcher.BeginInvoke at Background priority)."],"exampleFix":"// before\nvoid OnRendering(object sender, EventArgs e) {\n    if (closed) { UpdateVisual(); } // MediaContext read-only -> throws\n}\n// after\nvoid OnRendering(object sender, EventArgs e) {\n    if (closed) return; // or: Unsubscribe on Closed\n}\nprivate void Window_Closed(object sender, EventArgs e) {\n    CompositionTarget.Rendering -= OnRendering;\n}","handlingStrategy":"type-guard","validationCode":"if (window.IsClosed || Application.Current == null || Application.Current.Dispatcher.HasShutdownStarted) return; // skip render-callback work","typeGuard":"bool CanMutateVisuals(Visual v) =>\n    v != null && !v.Dispatcher.HasShutdownStarted && v.Dispatcher.CheckAccess();","tryCatchPattern":"try { MutateVisual(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"not allowed\")) { /* context became read-only: skip work */ }","preventionTips":["Unsubscribe CompositionTarget.Rendering in Unloaded/Closed","Always marshal visual mutations to the owning Dispatcher","Track shutdown state with a flag checked at the top of render callbacks","Avoid doing visual work in finalizers or process-exit handlers"],"tags":["wpf","media-context","read-only","thread-safety","shutdown"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}