{"record":{"id":"a349a35687e8a34a","repo":"elsa-workflows/elsa-core","slug":"transportfailure","errorCode":"TransportFailure","errorMessage":"ProviderHttpException(ProviderHttpFailure.TransportFailure)","messagePattern":"ProviderHttpException\\(ProviderHttpFailure\\.TransportFailure\\)","errorType":"error_code","errorClass":"ProviderHttpException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.ExternalAuthentication/Services/ProviderHttpClientFactory.cs","lineNumber":126,"sourceCode":"\n                return new(response.StatusCode, await ReadResponseBodyAsync(response, kind, timeout.Token));\n            }\n        }\n        catch (OutboundDestinationException)\n        {\n            throw new ProviderHttpException(ProviderHttpFailure.DestinationRejected);\n        }\n        catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)\n        {\n            throw new ProviderHttpException(ProviderHttpFailure.Timeout);\n        }\n        catch (ProviderHttpException)\n        {\n            throw;\n        }\n        catch (Exception) when (!cancellationToken.IsCancellationRequested)\n        {\n            throw new ProviderHttpException(ProviderHttpFailure.TransportFailure);\n        }\n    }\n\n    private async Task<byte[]> ReadResponseBodyAsync(HttpResponseMessage response, ProviderResponseKind kind, CancellationToken cancellationToken)\n    {\n        var limit = GetResponseLimit(kind);\n        var contentLength = response.Content.Headers.ContentLength;\n        if (contentLength is not null && contentLength > limit)\n            throw new ProviderHttpException(ProviderHttpFailure.ResponseTooLarge);\n\n        await using var input = await response.Content.ReadAsStreamAsync(cancellationToken);\n        await using var output = new MemoryStream();\n        var buffer = new byte[81920];\n        while (true)\n        {\n            var read = await input.ReadAsync(buffer, cancellationToken);\n            if (read == 0)\n                return output.ToArray();","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.ExternalAuthentication/Services/ProviderHttpClientFactory.cs#L108-L144","documentation":"ProviderHttpClientFactory wraps all outbound HTTP calls to the external identity provider (discovery, token, userinfo) and normalizes every failure into a ProviderHttpException with a ProviderHttpFailure code. TransportFailure is the catch-all branch: any exception that is not a cancellation, timeout, or already-classified provider error is rethrown as TransportFailure. It signals a low-level HTTP/network problem (DNS, TLS, connection reset, malformed response stream) rather than an application-level rejection.","triggerScenarios":"SendAsync (invoked via GetAsync or PostFormAsync) encounters an unexpected Exception during request transmission or response read while the caller's cancellationToken is NOT cancelled — e.g., HttpClient throws HttpRequestException on connection failure, TLS handshake error, or socket reset.","commonSituations":"Identity provider host unreachable (wrong authority URL, DNS failure), firewall/proxy blocking egress from a container or Kubernetes pod, TLS certificate issues (self-signed certs, expired CA), transient network blips in clustered deployments, or IPv6/IPv4 resolution problems.","solutions":["Verify the provider authority/base URL is correct and reachable from the machine running Elsa (curl the discovery endpoint, e.g. https://<authority>/.well-known/openid-configuration).","Check network egress: firewall rules, proxy env vars (HTTP_PROXY/HTTPS_PROXY), and DNS resolution inside containers; add the CA certificate to the trust store if TLS interception is in place.","Retry the operation — transport failures are often transient; configure HttpClient retry policies (Polly) at the HttpClient level.","Inspect the inner exception/log output for the original Exception details to distinguish DNS vs TLS vs connection-reset causes."],"exampleFix":"// before: app configured with unreachable authority\noptions.Authority = \"https://idp.internal.local\";\n// after: verify reachability and use correct host/port\noptions.Authority = \"https://idp.internal.local:8443\"; // ensure DNS + egress + trust chain allow this","handlingStrategy":"retry","validationCode":"// Reachability pre-check before invoking provider calls\nusing var ping = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };\nvar resp = await ping.GetAsync(new Uri(new Uri(authority), \"/.well-known/openid-configuration\"));\nif (!resp.IsSuccessStatusCode) throw new InvalidOperationException(\"Provider authority unreachable\");","typeGuard":null,"tryCatchPattern":"try\n{\n    await providerClient.GetAsync(url, ProviderResponseKind.Discovery);\n}\ncatch (ProviderHttpException pex) when (pex.Failure == ProviderHttpFailure.TransportFailure)\n{\n    logger.LogWarning(pex, \"Transport failure contacting provider; will retry\");\n    // retry with backoff or fail over to alternate authority\n}","preventionTips":["Health-check the provider authority at startup and before critical flows.","Configure Polly-style retry with exponential backoff on the underlying HttpClient.","Ensure container/pod egress rules and DNS allow the provider host.","Install the correct CA certificates when TLS interception proxies are present."],"tags":["network","http","oidc","transport"],"backgroundTag":"network-request-failed","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}