dotnet/wpf · error · ArgumentException

SR.Format(SR.TextCompositionManager_TextCompositionHasDone…

Error message

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

What it means

UnsafeUpdateComposition throws ArgumentException when the composition's Stage is TextCompositionStage.Done, i.e. the composition was already completed and cannot be updated further. Completed compositions are terminal in WPF's lifecycle.

Solutions

  1. Discard updates once Stage == Done; create a new composition for further input.
  2. Check composition.Stage before calling UpdateComposition and skip terminal compositions.
  3. Order the calls strictly: Start → Update* → Complete, with no late updates after Complete.

Example fix

// before
TextCompositionManager.CompleteComposition(composition);
TextCompositionManager.UpdateComposition(composition); // throws
// after
TextCompositionManager.CompleteComposition(composition);
// further text requires a new composition
Defensive patterns

Strategy: validation

Validate before calling

if (composition.Stage == TextCompositionStage.Done) return; // composition is finished; ignore late updates

Type guard

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

Try / catch

try { TextCompositionManager.UpdateComposition(composition); } catch (ArgumentException ex) { /* composition already done; drop the update */ }

Prevention

When it happens

Trigger: Calling TextCompositionManager.UpdateComposition after CompleteComposition (or after PostProcessInput finished the composition).

Common situations: Queued update work (e.g. a Dispatcher.BeginInvoke callback) running after the composition completed; asynchronous IME results arriving late for an already-finished composition.

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

Appendix: source

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

        }

        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);

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

View on GitHub (pinned to 81131a70a4)