{"record":{"id":"06b9b4db606511a2","repo":"elsa-workflows/elsa-core","slug":"responsetoolarge","errorCode":"ResponseTooLarge","errorMessage":"ProviderHttpException(ProviderHttpFailure.ResponseTooLarge)","messagePattern":"ProviderHttpException\\(ProviderHttpFailure\\.ResponseTooLarge\\)","errorType":"error_code","errorClass":"ProviderHttpException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.ExternalAuthentication/Services/ProviderHttpClientFactory.cs","lineNumber":135,"sourceCode":"        {\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();\n\n            if (output.Length + read > limit)\n                throw new ProviderHttpException(ProviderHttpFailure.ResponseTooLarge);\n\n            await output.WriteAsync(buffer.AsMemory(0, read), cancellationToken);\n        }\n    }\n\n    private long GetResponseLimit(ProviderResponseKind kind) => kind switch","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.ExternalAuthentication/Services/ProviderHttpClientFactory.cs#L117-L153","documentation":"Before reading the provider response body, ReadResponseBodyAsync checks the Content-Length header against the configured size limit for the response kind (token, userinfo, or discovery). If the declared body exceeds the limit, the factory immediately aborts with ProviderHttpFailure.ResponseTooLarge instead of buffering an oversized payload. This protects the workflow host from memory exhaustion via huge provider responses.","triggerScenarios":"SendAsync calls ReadResponseBodyAsync and response.Content.Headers.ContentLength is not null and exceeds GetResponseLimit(kind) — i.e., the configured MaximumTokenResponseBytes / MaximumUserInfoResponseBytes / MaximumDiscoveryResponseBytes (via ProviderEgress options).","commonSituations":"Discovery document unexpectedly large (provider returns huge metadata), token endpoint returning bloated JWT/access-token payloads, misconfigured (too small) egress limits after switching identity providers, or a misbehaving/misconfigured provider returning an unexpected body on a success status code.","solutions":["Increase the egress limit in Elsa's provider options: raise MaximumTokenResponseBytes / MaximumUserInfoResponseBytes / MaximumDiscoveryResponseBytes under ProviderEgress to a value above the observed Content-Length.","Inspect the actual provider response (curl with -i) to confirm the body size is legitimate and not a provider misconfiguration.","If the provider is sending unexpectedly large bodies (e.g., huge error pages with 200 status), fix the provider/issuer configuration instead of raising limits indefinitely."],"exampleFix":"// before (appsettings.json)\n\"ProviderEgress\": { \"MaximumDiscoveryResponseBytes\": 32768 }\n// after\n\"ProviderEgress\": { \"MaximumDiscoveryResponseBytes\": 262144 }","handlingStrategy":"validation","validationCode":"// Before calling, check expected response size against configured limits\nvar limit = egressOptions.MaximumDiscoveryResponseBytes;\nusing var head = new HttpRequestMessage(HttpMethod.Get, discoveryUrl);\nhead.Headers.Prefetch = true; // or issue a HEAD/Range request\nvar probe = await httpClient.SendAsync(head);\nif (probe.Content.Headers.ContentLength is > 0 && probe.Content.Headers.ContentLength > limit)\n    throw new InvalidOperationException($\"Discovery document {probe.Content.Headers.ContentLength} exceeds limit {limit}\");","typeGuard":null,"tryCatchPattern":"try\n{\n    var body = await providerClient.GetAsync(url, ProviderResponseKind.UserInfo);\n}\ncatch (ProviderHttpException pex) when (pex.Failure == ProviderHttpFailure.ResponseTooLarge)\n{\n    logger.LogError(\"Provider response exceeded configured egress limit\");\n}","preventionTips":["Size ProviderEgress limits to comfortably exceed the largest legitimate response from your identity provider.","Measure real response sizes with curl -i after any provider migration.","Reduce requested scopes/claims to keep token and userinfo payloads small."],"tags":["http","payload-size","oidc","configuration"],"backgroundTag":"payload-too-large","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"}