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
- Discard updates once Stage == Done; create a new composition for further input.
- Check composition.Stage before calling UpdateComposition and skip terminal compositions.
- 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
- Cancel pending async/queued updates when a composition completes.
- Treat Stage == Done as terminal everywhere.
- Prefer creating a new composition for post-completion input.
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
- SR.Format(SR.TextCompositionManager_TextCompositionHasStarte…
- SR.Format(SR.TextCompositionManager_TextCompositionNotStarte…
- CurrentFixedPageWriter uninitialized
- FixedPageReader
- SR.AnnotationServiceNotEnabled
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)