dotnet/wpf · error · ArgumentException

SR.InvalidEventHandle

Error message

SR.InvalidEventHandle

What it means

ByteRangeDownloader's constructor requires a valid, open SafeFileHandle-backed event handle; it signals this handle when asynchronous download work completes. If the handle is null, invalid, or already closed, it throws ArgumentException keyed by SR.InvalidEventHandle.

Solutions

  1. Create a fresh valid AutoResetEvent/ManualResetEvent handle (via its SafeWaitHandle) and pass it before any disposal
  2. Check eventHandle.IsInvalid/IsClosed before constructing
  3. If the handle was closed, recreate it rather than reusing the stale handle

Example fix

// before
var ev = new AutoResetEvent(false);
ev.Dispose();
new ByteRangeDownloader(uri, ev.SafeWaitHandle, timeout);
// after
using var ev = new AutoResetEvent(false);
if (!ev.SafeWaitHandle.IsInvalid && !ev.SafeWaitHandle.IsClosed)
    new ByteRangeDownloader(uri, ev.SafeWaitHandle, timeout);
Defensive patterns

Strategy: validation

Validate before calling

bool validHandle = h != null && !h.IsInvalid && !h.IsClosed;

Type guard

static bool IsValidWaitHandle(SafeWaitHandle? h) => h is { IsInvalid: false, IsClosed: false };

Try / catch

try { var d = new ByteRangeDownloader(uri, handle, timeout); } catch (ArgumentException ex) when (ex.ParamName == "eventHandle") { handle = new AutoResetEvent(false).SafeWaitHandle; }

Prevention

When it happens

Trigger: Calling the public ByteRangeDownloader constructor with an eventHandle that is null, has IsInvalid==true, or IsClosed==true (e.g. a handle disposed elsewhere or never created via CreateEvent).

Common situations: The event handle was disposed by another thread before the constructor ran, or a failed CreateEvent (returns null/invalid) result is passed through unchecked.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/a4f9cdcb81ec2543. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/IO/Packaging/ByteRangeDownloader.cs:411

        /// <summary>
        /// Constructor for ByteRangeDownloader
        /// </summary>
        private ByteRangeDownloader(Uri requestedUri, SafeWaitHandle eventHandle)
        {
            ArgumentNullException.ThrowIfNull(requestedUri);

            // Ensure uri is correct scheme (http or https) Do case-sensitive comparison since Uri.Scheme contract is to return in lower case only.
            if (!string.Equals(requestedUri.Scheme, Uri.UriSchemeHttp, StringComparison.Ordinal) && !string.Equals(requestedUri.Scheme, Uri.UriSchemeHttps, StringComparison.Ordinal))
            {
                throw new ArgumentException(SR.InvalidScheme, nameof(requestedUri));
            }

            ArgumentNullException.ThrowIfNull(eventHandle);

            if (eventHandle.IsInvalid || eventHandle.IsClosed)
            {
                throw new ArgumentException(SR.InvalidEventHandle, nameof(eventHandle));
            }

            _requestedUri = requestedUri;
            _eventHandle = eventHandle;
        }

        /// <summary>
        /// Check if it has been errored out from the worker thread and re-throw the exception that was
        /// thrown from the worker thread
        /// </summary>
        /// <remarks>No need to lock in this function since the caller always locks before making this call</remarks>
        private void CheckErroredOutCondition()
        {
            if (_erroredOut)
            {
                throw new InvalidOperationException(SR.ByteRangeDownloaderErroredOut, _erroredOutException);
            }
        }

View on GitHub (pinned to 81131a70a4)