dotnet/wpf · error · WebException

WebResponseFailure

Error message

WebResponseFailure

What it means

PackWebResponse performs its real work on a background thread; consumers block in WaitForResponse, which rethrows the outcome. If the worker signaled _responseError without an accompanying exception object, WaitForResponse throws WebException(SR.WebResponseFailure); otherwise it rethrows the original exception. This pattern is hit by GetResponseStream, InnerResponse, Headers, ResponseUri, IsFromCache, and ContentType.

Solutions

  1. Inspect and fix the underlying cause (check inner _responseException / inner WebException status — DNS, 404, TLS, etc.).
  2. Retry the request if the failure was transient network error.
  3. Ensure the request/response objects are not disposed or aborted before the response is consumed.
  4. Validate the served content is a valid package before consuming it.

Example fix

// before
var resp = req.GetResponse();
var s = resp.GetResponseStream(); // WebResponseFailure here
// after
try {
    var s = req.GetResponse().GetResponseStream();
} catch (WebException ex) {
    // inspect ex.Status / inner exception, retry or surface
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: ensure request not disposed and outer transport URI is reachable
if (req == null || req.RequestUri.HostNameType == UriHostNameType.Unknown) throw new InvalidOperationException("invalid pack request");

Try / catch

try { return resp.GetResponseStream(); }
catch (WebException ex) when (ex.Status == WebExceptionStatus.ConnectFailure || ex.Status == WebExceptionStatus.Timeout) { /* retry with backoff */ }
catch (WebException ex) { /* surface inner exception ex.InnerException */ throw; }

Prevention

When it happens

Trigger: Accessing any PackWebResponse result member after the asynchronous response worker failed — e.g. underlying WebRequest.GetResponse threw, stream read failed, or container open failed on the worker thread.

Common situations: Network failure or server error while downloading the outer package; invalid package bytes that break Package.Open on the background thread; aborted/disposed request racing with a response access.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/IO/Packaging/PackWebResponse.cs:847

        /// </summary>
        private void WaitForResponse()
        {
#if DEBUG
            if (PackWebRequestFactory._traceSwitch.Enabled)
                System.Diagnostics.Trace.TraceInformation(
                        DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " +
                        Environment.CurrentManagedThreadId + ": " +
                        "PackWebResponse.WaitForResponse()");
#endif
            // wait for the response callback
            _responseAvailable.WaitOne();

            // We get here only when the other thread signals.
            // Need to inspect for errors and throw if there was trouble on the other thread.
            if (_responseError)
            {
                if (_responseException == null)
                    throw new WebException(SR.WebResponseFailure);
                else
                    throw _responseException;   // throw literal exception if there is one
            }
        }

        /// <summary>
        /// Timeout callback
        /// </summary>
        /// <param name="stateInfo"></param>
        private void TimeoutCallback(Object stateInfo)
        {
            lock (_lockObject)   // prevent race condition accessing _timeoutTimer, _disposed, _responseAvailable
            {
                // If disposed, the message is too late
                // Exit early and don't access members as they have been disposed
                // Let Close() method clean up our Timer object
                if (_disposed)
                    return;

View on GitHub (pinned to 81131a70a4)