Flow-Launcher/Flow.Launcher · warning · Win32Exception

Error registering for power notifications: {Marshal.GetLastW

Error message

Error registering for power notifications: {Marshal.GetLastWin32Error()}

What it means

Thrown as Win32Exception when PowerRegisterSuspendResumeNotification returns anything other than ERROR_SUCCESS, leaving _handle as HPOWERNOTIFY.Null. The message includes Marshal.GetLastWin32Error() to surface the OS-level reason. This API registers a callback to receive sleep/resume notifications and normally only fails under specific OS/security conditions.

Source

Thrown at Flow.Launcher.Infrastructure/Win32Helper.cs:978

            _func = func;
            _callback = new PDEVICE_NOTIFY_CALLBACK_ROUTINE(DeviceNotifyCallback);
            _recipient = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS()
            {
                Callback = _callback,
                Context = null
            };

            _recipientHandle = new StructSafeHandle<DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS>(_recipient);
            _handle = PInvoke.PowerRegisterSuspendResumeNotification(
                REGISTER_NOTIFICATION_FLAGS.DEVICE_NOTIFY_CALLBACK,
                _recipientHandle,
                out var handle) == WIN32_ERROR.ERROR_SUCCESS ?
                new HPOWERNOTIFY(new IntPtr(handle)) :
                HPOWERNOTIFY.Null;
            if (_handle.IsNull)
            {
                throw new Win32Exception("Error registering for power notifications: " + Marshal.GetLastWin32Error());
            }
        }

        /// <summary>
        /// Unregisters the sleep mode listener.
        /// </summary>
        public static void UnregisterSleepModeListener()
        {
            if (!_handle.IsNull)
            {
                PInvoke.PowerUnregisterSuspendResumeNotification(_handle);
                _handle = HPOWERNOTIFY.Null;
                _func = null;
                _callback = null;
                _recipientHandle = null;
            }
        }

View on GitHub (pinned to 7fc63b07bb)

Solutions

  1. Decode Marshal.GetLastWin32Error() from the message (e.g. 87 ERROR_INVALID_PARAMETER, 5 ERROR_ACCESS_DENIED) to classify.
  2. Verify the DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS and the callback delegate are kept alive (not GC'd) for the registration's lifetime — the _callback field is allocated for this reason; ensure it isn't nulled.
  3. Confirm the OS supports PowerRegisterSuspendResumeNotification (Windows Vista+, desktop session).
  4. Catch Win32Exception at the caller and degrade to a polling/lesser mechanism for power-state awareness if registration is unavailable.
  5. Re-check the P/Invoke signature against the current Windows SDK if the HRESULT is unexpected.

Example fix

// before
if (_handle.IsNull)
    throw new Win32Exception("Error registering for power notifications: " + Marshal.GetLastWin32Error());

// after — include the HRESULT and degrade gracefully
if (_handle.IsNull)
{
    var err = Marshal.GetLastWin32Error();
    Log.Exception(nameof(Win32Helper), $"PowerRegisterSuspendResumeNotification failed (Win32 error {err}); power-state tracking disabled", null);
    // do not throw — continue without sleep/resume notifications
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try { Win32Helper.RegisterSleepModeListener(callback); }
catch (Win32Exception ex) when (ex.Message.Contains("power notifications"))
{ Log.Warn(...); // continue without sleep/resume notifications }

Prevention

When it happens

Trigger: The OS rejected the callback registration due to an invalid recipient structure, a marshalling failure of the DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS, or (rarely) insufficient privilege; running on a Windows edition/configuration that restricts power notifications; the StructSafeHandle holding _recipient was disposed or invalid at call time; a P/Invoke signature mismatch producing a non-SUCCESS return.

Common situations: An older/locked-down Windows build (kiosk, embedded) disabling power notification registration; a bug in the StructSafeHandle marshalling causing the callback pointer to be invalid; running under a heavily restricted service account; a CsWin32 generator mismatch producing wrong binding for PowerRegisterSuspendResumeNotification.

Related errors


AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13). Data as JSON: /api/errors/265b89591c2e72a6. Report an issue: GitHub.