dotnet/wpf · error · InvalidOperationException
SR.MediaContext_InfiniteLayoutLoop
Error message
SR.MediaContext_InfiniteLayoutLoop
What it means
The MediaContext render-callback drain loop (reached via the public render path) caps iterations at 153; if handlers queued via Dispatcher/Render keep re-registering Render-on-load callbacks so the list never empties, it throws InvalidOperationException(SR.MediaContext_InfiniteLayoutLoop). It detects endless layout/arrange feedback in a single render pass.
Solutions
- Find the element invalidating itself during render/layout (use WPF Visual Studio diagnostics / Layout rounding breakpoints) and remove that call.
- Move InvalidateArrange/InvalidateMeasure calls out of OnRender into event handlers that run once (Loaded, PropertyChanged) with re-entrancy guards.
- Use a boolean flag to prevent re-triggering layout while the same pass is in flight.
- Coalesce repeated invalidations; only invalidate when a value actually changed (compare old/new).
Example fix
// before
protected override void OnRender(DrawingContext dc) {
base.OnRender(dc);
InvalidateMeasure(); // endless layout loop
}
// after
private double _lastValue;
protected override void OnRender(DrawingContext dc) {
base.OnRender(dc);
if (Math.Abs(Value - _lastValue) > 0.001) { _lastValue = Value; InvalidateMeasure(); }
} Defensive patterns
Strategy: validation
Validate before calling
private bool _layoutPending;
void RequestLayout() {
if (_layoutPending) return; // coalesce; prevents endless invalidate cycle
_layoutPending = true;
Dispatcher.BeginInvoke(() => { _layoutPending = false; InvalidateMeasure(); });
} Try / catch
try { DoCustomLayout(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("layout")) { BreakInvalidationCycle(); Log("infinite layout loop"); } Prevention
- Never call InvalidateMeasure/InvalidateArrange from OnRender
- Only invalidate when a value actually changed (compare before assigning)
- Avoid cross-invalidating controls from MeasureOverride/ArrangeOverride
- Use LayoutUpdated only for observation, never for triggering layout
When it happens
Trigger: A single Dispatcher render pass where InvokeOnRender callbacks (registered via CompositionTarget.Rendering-like Render hooks or InvalidateArrange in OnRender) keep adding new callbacks each iteration past 153 rounds.
Common situations: Code that calls InvalidateMeasure/InvalidateArrange from OnRender or a render callback of the same element, custom controls invalidating each other in MeasureOverride/ArrangeOverride cycles, or LayoutUpdated handlers forcing another layout.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- SR.MediaContext_InfiniteTickLoop
- 0x80040206
- ArgumentNullException: child
- SR.ArrangeReentrancyInvalid
- SR.ArrangeReentrancyInvalid
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/786bb2b9371709fb.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/MediaContext.cs:1928
/// <summary>
/// Calls all _invokeOnRenderCallbacks until no more are added
/// </summary>
private void FireInvokeOnRenderCallbacks()
{
int callbackLoopCount = 0;
int count = InvokeOnRenderCallbacksCount;
// This outer loop is to re-run layout in case the app causes a layout to get enqueued in response
// to a Loaded event. In this case we would like to re-run layout before we allow render.
do
{
while (count > 0)
{
callbackLoopCount++;
if (callbackLoopCount > 153)
{
throw new InvalidOperationException(SR.MediaContext_InfiniteLayoutLoop);
}
FrugalObjectList<InvokeOnRenderCallback> callbacks = _invokeOnRenderCallbacks;
_invokeOnRenderCallbacks = null;
for (int i = 0; i < count; i++)
{
callbacks[i].DoWork();
}
count = InvokeOnRenderCallbacksCount;
}
// Fire all the pending Loaded events before Render happens
// but after the layout storm has subsided
FireLoadedPendingCallbacks();
count = InvokeOnRenderCallbacksCount;View on GitHub (pinned to 81131a70a4)