dotnet/wpf · error · InvalidOperationException

SR.ByteRangeDownloaderErroredOut

Error message

SR.ByteRangeDownloaderErroredOut

What it means

ByteRangeDownloader enters a terminal error state (_erroredOut) after an asynchronous download failure; once set, all further use is refused with InvalidOperationException(SR.ByteRangeDownloaderErroredOut) wrapping the original exception. The instance can never recover — you must discard it and create a new one.

Solutions

  1. Inspect the InnerException for the root cause (network/HTTP failure)
  2. Create a new ByteRangeDownloader instance and retry the request
  3. Add connectivity/availability checks before retrying

Example fix

// before
downloader.RequestByteRanges(ranges);
// after
try { downloader.RequestByteRanges(ranges); }
catch (InvalidOperationException) { downloader = new ByteRangeDownloader(uri, handle, timeout); }
Defensive patterns

Strategy: try-catch

Validate before calling

// no public API to check _erroredOut; guard by catching

Try / catch

try { downloader.RequestByteRanges(ranges); } catch (InvalidOperationException ex) { downloader = new ByteRangeDownloader(uri, handle, timeout); /* retry once */ }

Prevention

When it happens

Trigger: Calling RequestByteRanges or GetDownloadedByteRanges on a ByteRangeDownloader instance after an internal download/response error already occurred (inner exception via _erroredOutException).

Common situations: A network drop or HTTP failure during an earlier async range request poisoned the downloader; callers keep using the stale instance for subsequent ranges.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

            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);
            }
        }

        /// <summary>
        /// Download the requested bytes
        /// </summary>
        private HttpWebRequest CreateHttpWebRequest(int[,] byteRanges)
        {
            HttpWebRequest request;

            // Create the request object
            request = (HttpWebRequest)WpfWebRequestHelper.CreateRequest(_requestedUri);
            request.ProtocolVersion = HttpVersion.Version11;
            request.Method = "GET";

            // Set the Proxy to Empty one; If we don't set this to empty one, it will try to find one for us
            //  and ends up triggering JScript in another assembly. This will throw PolicyException since the JScript
            //  dll doesn't have execution right. This is a bug in CLR; supposed to be fixed later

View on GitHub (pinned to 81131a70a4)