dotnet/wpf · error · ArgumentException
SR.Format(SR.TextCompositionManager_TextCompositionHasStarte…
Error message
SR.Format(SR.TextCompositionManager_TextCompositionHasStarted, "composition")
What it means
UnsafeStartComposition throws ArgumentException when the composition's Stage is already past TextCompositionStage.None, i.e. StartComposition is being called on a composition that has already been started. WPF tracks composition lifecycle to prevent duplicate start events.
Solutions
- Create a fresh TextComposition for each start instead of reusing one.
- Check composition.Stage == TextCompositionStage.None before calling StartComposition.
- Track whether StartComposition was already invoked for that composition instance.
Example fix
// before
TextCompositionManager.StartComposition(composition);
TextCompositionManager.StartComposition(composition); // throws
// after
if (composition.Stage == TextCompositionStage.None)
TextCompositionManager.StartComposition(composition); Defensive patterns
Strategy: validation
Validate before calling
if (composition.Stage != TextCompositionStage.None) throw new InvalidOperationException("Composition already started."); Type guard
static bool CanStart(TextComposition c) => c != null && c.Stage == TextCompositionStage.None;
Try / catch
try { TextCompositionManager.StartComposition(composition); } catch (ArgumentException ex) { /* already started */ } Prevention
- Track started compositions in a set keyed by instance.
- Never reuse a TextComposition across start cycles.
- Centralize lifecycle calls in one helper that checks Stage first.
When it happens
Trigger: Calling TextCompositionManager.StartComposition twice on the same TextComposition, or reusing a composition that already went through the start pipeline (via PreProcessInput/PostProcessInput).
Common situations: Caching a TextComposition and retrying StartComposition after a handler suppressed the first pass; event re-entrancy when input handlers themselves call StartComposition.
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_TextCompositionNotStarte…
- SR.Format(SR.TextCompositionManager_TextCompositionHasDone…
- CurrentFixedPageWriter uninitialized
- FixedPageReader
- SR.AnnotationServiceNotEnabled
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/34703300d3c426f1.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextCompositionManager.cs:319
//------------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
private static bool UnsafeStartComposition(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_TextCompositionHasStarted, "composition"));
}
composition.Stage = TextCompositionStage.Started;
TextCompositionEventArgs textargs = new TextCompositionEventArgs(composition._InputDevice, composition)
{
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"));View on GitHub (pinned to 81131a70a4)