dotnet/wpf · error · ArgumentException

SR.Format(SR.TextCompositionManager_TextCompositionNotStarte…

Error message

SR.Format(SR.TextCompositionManager_TextCompositionNotStarted, "composition")

What it means

UnsafeUpdateComposition throws ArgumentException when the composition's Stage is still TextCompositionStage.None, meaning UpdateComposition was called before StartComposition. WPF requires the start/update/complete lifecycle order.

Solutions

  1. Call TextCompositionManager.StartComposition(composition) before any UpdateComposition call.
  2. Guard the update: only update when composition.Stage == TextCompositionStage.Started.
  3. Fix earlier errors in the start path that left the stage at None.

Example fix

// before
TextCompositionManager.UpdateComposition(composition); // never started
// after
TextCompositionManager.StartComposition(composition);
TextCompositionManager.UpdateComposition(composition);
Defensive patterns

Strategy: validation

Validate before calling

if (composition.Stage == TextCompositionStage.None) throw new InvalidOperationException("Call StartComposition before UpdateComposition.");

Type guard

static bool CanUpdate(TextComposition c) => c != null && c.Stage == TextCompositionStage.Started;

Try / catch

try { TextCompositionManager.UpdateComposition(composition); } catch (ArgumentException ex) { /* not started yet */ }

Prevention

When it happens

Trigger: Calling TextCompositionManager.UpdateComposition on a composition for which StartComposition was never called (or failed before setting Stage to Started).

Common situations: Skipping the StartComposition step in custom IME emulation; calling UpdateComposition after a start attempt was aborted by an exception or a suppressed input event.

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/4a7e1e9e7131c6ef. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextCompositionManager.cs:342

            {
                RoutedEvent = TextCompositionManager.PreviewTextInputStartEvent,
                Source = composition.Source
            };
            return composition._InputManager.ProcessInput(textargs);
        }

        private static bool UnsafeUpdateComposition(TextComposition composition)
        {
            ArgumentNullException.ThrowIfNull(composition);

            if (composition._InputManager == null)
            {
                throw new ArgumentException(SR.Format(SR.TextCompositionManager_NoInputManager, "composition"));
            }

            if (composition.Stage == TextCompositionStage.None)
            {
                throw new ArgumentException(SR.Format(SR.TextCompositionManager_TextCompositionNotStarted, "composition"));
            }

            if (composition.Stage == TextCompositionStage.Done)
            {
                throw new ArgumentException(SR.Format(SR.TextCompositionManager_TextCompositionHasDone, "composition"));
            }

            TextCompositionEventArgs textargs = new TextCompositionEventArgs(composition._InputDevice, composition)
            {
                RoutedEvent = TextCompositionManager.PreviewTextInputUpdateEvent,
                Source = composition.Source
            };
            return composition._InputManager.ProcessInput(textargs);
        }

        private static bool UnsafeCompleteComposition(TextComposition composition)
        {
            ArgumentNullException.ThrowIfNull(composition);

View on GitHub (pinned to 81131a70a4)