dotnet/maui · critical · Exception
Unable to initialize GDI+
Error message
Unable to initialize GDI+
What it means
NativeMethods.Startup throws Exception("Unable to initialize GDI+") when GdiplusStartup returns a Status other than Ok. GDI+ must be initialised exactly once per process before any GDI+ rendering API is used; a non-Ok status means the runtime could not load or initialise GDI+ (gdiplus.dll).
Source
Thrown at src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/NativeMethods.cs:1614
protected override bool ReleaseHandle()
{
Status s = NativeMethods.GdiplusShutdown(this.handle);
return s == Status.Ok;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
[SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
public static SafeGdiplusStartupToken Startup()
{
IntPtr unsafeHandle;
StartupOutput output;
Status s = NativeMethods.GdiplusStartup(out unsafeHandle, new StartupInput(), out output);
if (s == Status.Ok)
{
SafeGdiplusStartupToken safeHandle = new SafeGdiplusStartupToken(unsafeHandle);
return safeHandle;
}
throw new Exception("Unable to initialize GDI+");
}
}
internal sealed class SafeConnectionPointCookie : SafeHandleZeroOrMinusOneIsInvalid
{
IConnectionPoint _cp;
// handle holds the cookie value.
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IConnectionPoint")]
public SafeConnectionPointCookie(IConnectionPointContainer target, object sink, Guid eventId)
: base(true)
{
Verify.IsNotNull(target, "target");
Verify.IsNotNull(sink, "sink");
Verify.IsNotDefault(eventId, "eventId");
handle = IntPtr.Zero;View on GitHub (pinned to f377ff1c5e)
Solutions
- Ensure gdiplus.dll is present and loadable (run sfc /scannow to repair system files).
- Confirm the process runs on a supported Windows desktop session.
- Avoid calling Startup concurrently; let the SafeGdiplusStartupToken singleton manage it.
- Free GDI+ resources (images, graphics) promptly to avoid exhaustion that can cause Startup to fail.
Example fix
// before
var token = NativeMethods.Startup(); // throws if gdiplus.dll missing
// after
if (!System.IO.File.Exists(System.IO.Path.Combine(Environment.SystemDirectory, "gdiplus.dll")))
throw new InvalidOperationException("gdiplus.dll not available");
var token = NativeMethods.Startup(); Defensive patterns
Strategy: validation
Validate before calling
if (!System.IO.File.Exists(System.IO.Path.Combine(Environment.SystemDirectory, "gdiplus.dll")))
throw new InvalidOperationException("gdiplus.dll not available");
var token = NativeMethods.Startup(); Type guard
static bool GdiplusAvailable =>
System.IO.File.Exists(System.IO.Path.Combine(Environment.SystemDirectory, "gdiplus.dll")); Try / catch
try { var token = NativeMethods.Startup(); }
catch (Exception ex) when (ex.Message.Contains("GDI+"))
{ /* repair system files or run on supported Windows; cannot recover at runtime */ } Prevention
- Ensure gdiplus.dll is present (run sfc /scannow if missing).
- Run on a supported Windows desktop session.
- Release GDI+ resources promptly to keep Startup succeeding.
When it happens
Trigger: GdiplusStartup fails due to missing/corrupt gdiplus.dll; out of memory or GDI+ object exhaustion; calling Startup concurrently without the SafeHandle guard; locked-down environment preventing native DLL load.
Common situations: Stripped Windows image lacking gdiplus.dll; sandboxed/app-container environment; corrupted system files; running on a non-Windows platform where the shell assembly is force-loaded.
Related errors
- Unable to create a device context from the specified device
- Unable to combine two HRGNs.
- Could not find or create a renderer for {view}
- Unable to find the required services. Please add all the req
- RootComponent requires a value for its Selector property, bu
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/f1daa541ee8f3d85.
Report an issue: GitHub.