dotnet/wpf · error · InvalidOperationException

SR.NotInInitialization

Error message

SR.NotInInitialization

What it means

GlyphRun implements ISupportInitialize so it can be built in two phases: BeginInit sets up the object, EndInit commits it. This InvalidOperationException is thrown by EndInit when the GlyphRun was never put into initializing state (BeginInit was not called, or EndInit was already called once). The library throws it because calling EndInit outside a BeginInit/EndInit pair is a programming error, not a runtime condition.

Solutions

  1. Ensure BeginInit() is called on the GlyphRun before EndInit(), as a matched pair.
  2. Guard the EndInit call with a check of the initialization state or a boolean flag you control.
  3. If you do not need deferred initialization, construct GlyphRun with its full constructor and drop the ISupportInitialize calls entirely.

Example fix

// before
var glyphRun = new GlyphRun(...);
((ISupportInitialize)glyphRun).EndInit(); // throws: never began init

// after
var glyphRun = new GlyphRun(...);
((ISupportInitialize)glyphRun).BeginInit();
// ... set properties ...
((ISupportInitialize)glyphRun).EndInit();
Defensive patterns

Strategy: validation

Validate before calling

static bool IsGlyphRunInitializing(GlyphRun run) =>
    run is ISupportInitialize && GlyphRunStateTracker.IsInitializing(run); // track your own BeginInit/EndInit pairing
// simplest practical guard: only call EndInit inside a scope where you called BeginInit
using var scope = GlyphInitScope.Begin(glyphRun); // helper that pairs BeginInit/EndInit

Type guard

static bool CanEndInit(ISupportInitialize obj, bool beginInitCalled) => beginInitCalled;

Try / catch

try { ((ISupportInitialize)glyphRun).EndInit(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("initialization")) { /* recreate GlyphRun via constructor instead */ }

Prevention

When it happens

Trigger: Calling ((ISupportInitialize)glyphRun).EndInit() without a preceding BeginInit(), calling EndInit twice for one BeginInit, or calling EndInit on a GlyphRun constructed normally via its constructor without ever using ISupportInitialize at all.

Common situations: XAML/baml deserialization code paths that end initialization out of order, hand-rolled object initializers that mirror the XAML pattern but forget BeginInit, refactored code that removed a BeginInit call while keeping EndInit.

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


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/7515ac057a1f843f. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphRun.cs:2308

                // Cannot initialize a GlyphRun that is completely initialized.
                throw new InvalidOperationException(SR.OnlyOneInitialization);
            }

            if (IsInitializing)
            {
                // Cannot initialize a GlyphRun that is already being initialized.
                throw new InvalidOperationException(SR.InInitialization);
            }

            IsInitializing = true;
        }

        void ISupportInitialize.EndInit()
        {
            if (!IsInitializing)
            {
                // Cannot EndInit a GlyphRun that is not being initialized.
                throw new InvalidOperationException(SR.NotInInitialization);
            }

            //
            // Fully initilize the GlyphRun. The method will check for consistency
            // between all the properties.
            //
            Initialize(
                _glyphTypeface,
                _bidiLevel,
                (_flags & GlyphRunFlags.IsSideways) != 0,
                _renderingEmSize,
                _pixelsPerDip,
                _glyphIndices,
                _baselineOrigin,
                // In case the layout mode is not Ideal then we cannot use ThousandthOfEmReal* since ThousandthOfEmReal* internally stores doubles as integers and hence there is some lost percision
                // that can result in glyphs that were pixel aligned be not so. This is not important for ideal layout but is of great importance for compatible with layout.
                (_advanceWidths == null ? null : ((_textFormattingMode != TextFormattingMode.Ideal) ? (IList<double>)(new List<double>()) : (IList<double>)(new ThousandthOfEmRealDoubles(_renderingEmSize, _advanceWidths)))),
                (_glyphOffsets == null ? null : ((_textFormattingMode != TextFormattingMode.Ideal) ? (IList<Point>)(new List<Point>()) : (IList<Point>)(new ThousandthOfEmRealPoints(_renderingEmSize, _glyphOffsets)))),

View on GitHub (pinned to 81131a70a4)