{"record":{"id":"34703300d3c426f1","repo":"dotnet/wpf","slug":"sr-format-sr-textcompositionmanager","errorCode":null,"errorMessage":"SR.Format(SR.TextCompositionManager_TextCompositionHasStarted, \"composition\")","messagePattern":"SR\\.Format\\(SR\\.TextCompositionManager_TextCompositionHasStarted, \"composition\"\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextCompositionManager.cs","lineNumber":319,"sourceCode":"\n        //------------------------------------------------------\n        //\n        //  Private Methods\n        //\n        //------------------------------------------------------\n\n        private static bool UnsafeStartComposition(TextComposition composition)\n        {\n            ArgumentNullException.ThrowIfNull(composition);\n\n            if (composition._InputManager == null)\n            {\n                throw new ArgumentException(SR.Format(SR.TextCompositionManager_NoInputManager, \"composition\"));\n            }\n\n            if (composition.Stage != TextCompositionStage.None)\n            {\n                throw new ArgumentException(SR.Format(SR.TextCompositionManager_TextCompositionHasStarted, \"composition\"));\n            }\n\n            composition.Stage = TextCompositionStage.Started;\n            TextCompositionEventArgs textargs = new TextCompositionEventArgs(composition._InputDevice, composition)\n            {\n                RoutedEvent = TextCompositionManager.PreviewTextInputStartEvent,\n                Source = composition.Source\n            };\n            return composition._InputManager.ProcessInput(textargs);\n        }\n\n        private static bool UnsafeUpdateComposition(TextComposition composition)\n        {\n            ArgumentNullException.ThrowIfNull(composition);\n\n            if (composition._InputManager == null)\n            {\n                throw new ArgumentException(SR.Format(SR.TextCompositionManager_NoInputManager, \"composition\"));","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextCompositionManager.cs#L301-L337","documentation":"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.","triggerScenarios":"Calling TextCompositionManager.StartComposition twice on the same TextComposition, or reusing a composition that already went through the start pipeline (via PreProcessInput/PostProcessInput).","commonSituations":"Caching a TextComposition and retrying StartComposition after a handler suppressed the first pass; event re-entrancy when input handlers themselves call StartComposition.","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."],"exampleFix":"// before\nTextCompositionManager.StartComposition(composition);\nTextCompositionManager.StartComposition(composition); // throws\n// after\nif (composition.Stage == TextCompositionStage.None)\n    TextCompositionManager.StartComposition(composition);","handlingStrategy":"validation","validationCode":"if (composition.Stage != TextCompositionStage.None) throw new InvalidOperationException(\"Composition already started.\");","typeGuard":"static bool CanStart(TextComposition c) => c != null && c.Stage == TextCompositionStage.None;","tryCatchPattern":"try { TextCompositionManager.StartComposition(composition); } catch (ArgumentException ex) { /* already started */ }","preventionTips":["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."],"tags":["wpf","text-composition","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}