{"record":{"id":"f41f29320d137052","repo":"dotnet/wpf","slug":"sr-verify-apartmentstate-template-verify-apartmentstate-arg","errorCode":null,"errorMessage":"SR.Verify_ApartmentState (template: Verify_ApartmentState, arg: requiredState)","messagePattern":"SR\\.Verify_ApartmentState \\(template: Verify_ApartmentState, arg: requiredState\\)","errorType":"exception","errorClass":"System.InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/Verify.cs","lineNumber":31,"sourceCode":"    internal static class Verify\n    {\n        /// <summary>\n        /// Ensure that the current thread's apartment state is what's expected.\n        /// </summary>\n        /// <param name=\"requiredState\">\n        /// The required apartment state for the current thread.\n        /// </param>\n        /// <param name=\"message\">\n        /// The message string for the exception to be thrown if the state is invalid.\n        /// </param>\n        /// <exception cref=\"InvalidOperationException\">\n        /// Thrown if the calling thread's apartment state is not the same as the requiredState.\n        /// </exception>\n        public static void IsApartmentState(ApartmentState requiredState)\n        {\n            if (Thread.CurrentThread.GetApartmentState() != requiredState)\n            {\n                throw new InvalidOperationException(SR.Format(SR.Verify_ApartmentState, requiredState));\n            }\n        }\n\n        /// <summary>\n        /// Ensure that an argument is neither null nor empty.\n        /// </summary>\n        /// <param name=\"value\">The string to validate.</param>\n        /// <param name=\"name\">The name of the parameter that will be presented if an exception is thrown.</param>\n        public static void IsNeitherNullNorEmpty(string value, string name)\n        {\n            // catch caller errors, mixing up the parameters.  Name should never be empty.\n            Debug.Assert(!string.IsNullOrEmpty(name));\n\n            // Notice that ArgumentNullException and ArgumentException take the parameters in opposite order :P\n            if (value == null)\n            {\n                throw new ArgumentNullException(name, SR.Verify_NeitherNullNorEmpty);\n            }","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/Verify.cs#L13-L49","documentation":"Verify.IsApartmentState asserts that the calling thread's COM apartment state (STA/MTA/Unknown) matches the state required by the API being called. WindowsBase throws InvalidOperationException because apartment affinity is a caller/threading contract, not an argument problem: the operation simply cannot run on a thread with the wrong apartment state. This is used by WPF APIs that require an STA thread (e.g. for UI or clipboard/ Freezable work).","triggerScenarios":"Calling an API that wraps Verify.IsApartmentState(ApartmentState.STA) (or a specific requiredState) from a thread whose Thread.GetApartmentState() differs - e.g. calling from a plain ThreadPool/Task thread or an MTA thread when STA is required.","commonSituations":"Creating WPF visuals, Freezables, or using STA-only COM interop from a background Task.Run thread; spawning a Thread without SetApartmentState(ApartmentState.STA) before Start(); hosting WPF in a console/service whose main thread is MTA.","solutions":["Before starting the thread, set Thread.CurrentThread.SetApartmentState(ApartmentState.STA) (must be called before Thread.Start()).","Move the call onto an STA thread: new Thread(...) { SetApartmentState = ApartmentState.STA } and marshal the result back.","If on the UI thread already, ensure the work runs via Dispatcher.Invoke/BeginInvoke on the STA UI dispatcher instead of a worker thread.","For Task-based code, use a dedicated STA scheduler/Thread rather than Task.Run (ThreadPool threads are MTA)."],"exampleFix":"// before\nTask.Run(() => CreateVisual()); // MTA thread -> InvalidOperationException\n// after\nvar t = new Thread(() => CreateVisual());\nt.SetApartmentState(ApartmentState.STA);\nt.Start();","handlingStrategy":"validation","validationCode":"if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)\n    throw new InvalidOperationException(\"This API requires an STA thread. Use SetApartmentState(ApartmentState.STA) before Thread.Start(), or dispatch to the UI thread.\");","typeGuard":"bool IsStaThread() => Thread.CurrentThread.GetApartmentState() == ApartmentState.STA;","tryCatchPattern":"try\n{\n    CallStaOnlyApi();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ApartmentState\"))\n{\n    RunOnStaThread(() => CallStaOnlyApi());\n}","preventionTips":["Always call thread.SetApartmentState(ApartmentState.STA) before Thread.Start() for WPF/COM work","Never call STA-only WPF APIs from Task.Run; use Dispatcher.Invoke or a dedicated STA thread","For services/console apps, mark main or the worker thread STA explicitly","Centralize STA-thread creation in a helper so ad-hoc threads can't forget it"],"tags":["threading","apartment-state","wpf","sta"],"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-21T21:30:21.729Z"}