dotnet/wpf · error · InvalidOperationException
SR.MediaContext_APINotAllowed
Error message
SR.MediaContext_APINotAllowed
What it means
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.
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).
Example fix
// before
void OnRendering(object sender, EventArgs e) {
if (closed) { UpdateVisual(); } // MediaContext read-only -> throws
}
// after
void OnRendering(object sender, EventArgs e) {
if (closed) return; // or: Unsubscribe on Closed
}
private void Window_Closed(object sender, EventArgs e) {
CompositionTarget.Rendering -= OnRendering;
} Defensive patterns
Strategy: type-guard
Validate before calling
if (window.IsClosed || Application.Current == null || Application.Current.Dispatcher.HasShutdownStarted) return; // skip render-callback work
Type guard
bool CanMutateVisuals(Visual v) =>
v != null && !v.Dispatcher.HasShutdownStarted && v.Dispatcher.CheckAccess(); Try / catch
try { MutateVisual(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("not allowed")) { /* context became read-only: skip work */ } Prevention
- 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
When it happens
Trigger: 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.
Common situations: CompositionTarget.Rendering handlers touching visuals after the host window is closed; background threads mutating visuals without Dispatcher dispatch; work scheduled in finalizers/shutdown hooks.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- 0x80040209
- Cannot remove signature from read-only file.
- Cannot sign read-only file.
- CollectionIsFixedSize
- Image_OriginalStreamReadOnly
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/8fe2fe54853632cc.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/MediaContext.cs:2298
/// <summary>
/// This function is registered with the MediaContext's TimeManager. It is called whenever
/// a clock managed by the TimeManager goes active, but only if there hasn't been already an
/// active clock. For now we start the animation thread in there.
/// </summary>
private void OnNeedTickSooner(object sender, EventArgs e)
{
PostRender();
}
/// <summary>
/// Checks if the current context can request the specified permissions.
/// </summary>
internal void VerifyWriteAccess()
{
if (!WriteAccessEnabled)
{
throw new InvalidOperationException(SR.MediaContext_APINotAllowed);
}
}
/// <summary>
/// Returns false if the MediaContext is currently read-only
/// </summary>
internal bool WriteAccessEnabled
{
get { return _readOnlyAccessCounter <= 0; }
}
/// <summary>
/// Methods to lock down the Visual tree for write access.
/// </summary>
internal void PushReadOnlyAccess()
{
_readOnlyAccessCounter++;
}View on GitHub (pinned to 81131a70a4)