dotnet/maui · critical · SystemException

Unable to create a device context from the specified device

Error message

Unable to create a device context from the specified device information.

What it means

NativeMethods.CreateDeviceContext (CreateIC path) throws SystemException("Unable to create a device context from the specified device information.") when the resulting SafeDC handle is invalid after CreateDC/CreateIC. The shell's standard interop wrapper treats an invalid GDI device-context handle as fatal because subsequent rendering/metrics calls would all fail.

Source

Thrown at src/Compatibility/Core/src/WPF/Microsoft.Windows.Shell/Standard/NativeMethods.cs:1488

		{
			SafeDC dc = null;
			try
			{
				// Should this really be on the driver parameter?
				dc = NativeMethods.CreateDC(deviceName, null, IntPtr.Zero, IntPtr.Zero);
			}
			finally
			{
				if (dc != null)
				{
					dc._created = true;
				}
			}

			if (dc.IsInvalid)
			{
				dc.Dispose();
				throw new SystemException("Unable to create a device context from the specified device information.");
			}

			return dc;
		}

		[SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public static SafeDC CreateCompatibleDC(SafeDC hdc)
		{
			SafeDC dc = null;
			try
			{
				IntPtr hPtr = IntPtr.Zero;
				if (hdc != null)
				{
					hPtr = hdc.handle;
				}
				dc = NativeMethods.CreateCompatibleDC(hPtr);
				if (dc == null)

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Run the code on an interactive desktop session (or mock the device-context dependency in CI).
  2. Validate the device name (lpszDevice) before calling CreateIC; fall back to DISPLAY or null.
  3. Monitor GDI handle count and release SafeDC handles promptly to avoid exhaustion.
  4. For services, run the rendering in a session-0 interactive process or use a virtual display.

Example fix

// before
using (var dc = NativeMethods.CreateIC("BadDevice", null, null, null)) { ... }

// after
var device = IsValidDeviceName("BadDevice") ? "BadDevice" : null;
using (var dc = NativeMethods.CreateIC(device, null, null, null)) { ... }
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(device) || !IsKnownDevice(device)) device = null;
using var dc = NativeMethods.CreateIC(device, null, null, null);

Type guard

static bool HasInteractiveDesktop =>
    System.Windows.Application.Current != null &&
    !System.Windows.Application.Current.Dispatcher.HasShutdownStarted;

Try / catch

try { using var dc = NativeMethods.CreateIC(device, null, null, null); }
catch (SystemException ex) when (ex.Message.Contains("device context"))
{ /* fall back to GetDC(IntPtr.Zero) or report headless env */ }

Prevention

When it happens

Trigger: Calling CreateDC/CreateIC with a device name or DEVMODE that the system rejects; running under a session with no display (services, RDP disconnect, headless CI); GDI handle exhaustion; corrupted display driver state.

Common situations: Headless CI/service context where no interactive desktop exists; invalid printer/display device name; GDI resource leak exhausting the session handle pool; remote session teardown mid-call.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/f37e0ced0da72462. Report an issue: GitHub.