dotnet/wpf · error · InvalidOperationException
SR.RequiresSTA
Error message
SR.RequiresSTA
What it means
A BitmapEffect (or derived effect) was constructed on a thread whose apartment state is not STA. WPF effects rely on STA-only components (Cicero, OLE, COM), so the constructor VerifyRequiresSTA path throws InvalidOperationException with SR.RequiresSTA when Thread.CurrentThread.GetApartmentState() != ApartmentState.STA.
Solutions
- Create and use the effect on the WPF UI (STA) thread, e.g. via Dispatcher.Invoke
- Mark the entry point with [STAThread] or start the thread with Thread.SetApartmentState(ApartmentState.STA)
- Pre-render into a static image/source on the STA thread, then consume the result on the worker thread
- Migrate to the modern Effect (shader) API, which does not carry the same STA requirement
Example fix
// before
Task.Run(() => new DropShadowBitmapEffect()); // MTA thread, throws
// after
Application.Current.Dispatcher.Invoke(() =>
{
var effect = new DropShadowBitmapEffect(); // STA UI thread
}); Defensive patterns
Strategy: try-catch
Validate before calling
static bool CanCreateBitmapEffect() =>
Thread.CurrentThread.GetApartmentState() == ApartmentState.STA; Try / catch
try { var effect = new DropShadowBitmapEffect(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("STA"))
{
// retry on the STA UI thread via Dispatcher.Invoke
} Prevention
- Create all WPF visuals/effects on the Dispatcher/UI thread
- Mark entry points [STAThread]; set ApartmentState.STA on threads that touch WPF
- Never construct effects inside Task.Run or thread-pool callbacks
- Prefer the modern Effect/PixelShader API for new code
When it happens
Trigger: new SomeBitmapEffect() on a background/MTA thread; creating effects inside Task.Run or a non-STA worker; console/service hosts without [STAThread] on Main.
Common situations: Unit test runners with MTA threads; headless image processing services creating WPF visuals off-thread; migrating legacy code to async workers; missing [STAThread] attribute after host change.
Understand the failure class
Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.
Related errors
- SR.Format(SR.AxRequiresApartmentThread, clsid.ToString())
- SR.PTProvider_VerifyAccess
- SR.RequiresSTA
- SR.Verify_ApartmentState (template: Verify_ApartmentState…
- ElementNotAvailableException
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/bde07146e2715d47.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Effects/BitmapEffect.cs:28
/// <summary>
/// BitmapEffect
/// </summary>
public abstract partial class BitmapEffect
{
#region Constructors
/// <summary>
/// Constructor
/// </summary>
protected BitmapEffect()
{
// STA Requirement
//
// Avalon doesn't necessarily require STA, but many components do. Examples
// include Cicero, OLE, COM, etc. So we throw an exception here if the
// thread is not STA.
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
{
throw new InvalidOperationException(SR.RequiresSTA);
}
}
#endregion
#region Protected Methods
/// <summary>
/// This method is called before calling GetOutput on an effect.
/// It gives a chance for the managed effect to update the properties
/// of the unmanaged object.
/// </summary>
[Obsolete(MS.Internal.Media.VisualTreeUtils.BitmapEffectObsoleteMessage)]
protected abstract void UpdateUnmanagedPropertyState(SafeHandle unmanagedEffect);
/// <summary>
/// Returns a safe handle to an unmanaged effect clone
/// </summary>View on GitHub (pinned to 81131a70a4)