{"record":{"id":"5510437c0be7dde7","repo":"Tyrrrz/DiscordChatExporter","slug":"request-to-url-failed-response-statuscode-to","errorCode":null,"errorMessage":"Request to '{url}' failed: {response.StatusCode.ToString().SeparateWords(' ').ToLowerInvariant()}.\nResponse content: {await response.Content.ReadAsStringAsync(cancellationToken)}","messagePattern":"Request to '(.+?)' failed: (.+?)\\.\nResponse content: (.+?)","errorType":"http","errorClass":"DiscordChatExporterException","httpStatus":null,"severity":"error","filePath":"DiscordChatExporter.Core/Discord/DiscordClient.cs","lineNumber":158,"sourceCode":"\n        if (!response.IsSuccessStatusCode)\n        {\n            throw response.StatusCode switch\n            {\n                HttpStatusCode.Unauthorized => throw new DiscordChatExporterException(\n                    \"Authentication token is invalid.\",\n                    true\n                ),\n\n                HttpStatusCode.Forbidden => throw new DiscordChatExporterException(\n                    $\"Request to '{url}' failed: forbidden.\"\n                ),\n\n                HttpStatusCode.NotFound => throw new DiscordChatExporterException(\n                    $\"Request to '{url}' failed: not found.\"\n                ),\n\n                _ => throw new DiscordChatExporterException(\n                    $\"\"\"\n                    Request to '{url}' failed: {response\n                        .StatusCode.ToString()\n                        .SeparateWords(' ')\n                        .ToLowerInvariant()}.\n                    Response content: {await response.Content.ReadAsStringAsync(\n                        cancellationToken\n                    )}\n                    \"\"\",\n                    true\n                ),\n            };\n        }\n\n        return await response.Content.ReadAsJsonAsync(cancellationToken);\n    }\n\n    private async ValueTask<JsonElement?> TryGetJsonResponseAsync(","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/Tyrrrz/DiscordChatExporter/blob/f6865c82167c3bfee4455da80a1f1ca5e71b95ad/DiscordChatExporter.Core/Discord/DiscordClient.cs#L140-L176","documentation":"Thrown as DiscordChatExporterException(isFatal=true) from the default arm of GetJsonResponseAsync's status switch for any non-success status not handled by 401/403/404 (e.g. 429 Too Many Requests, 5xx server errors, 400 Bad Request). The message embeds both the humanized status (words separated and lower-cased) and the raw response body to aid diagnosis. isFatal is set because these usually indicate systemic or server-side conditions.","triggerScenarios":"Any GetJsonResponseAsync call whose response status is not 200/401/403/404. The default switch arm at DiscordClient.cs:158 builds the message from `response.StatusCode.ToString().SeparateWords(' ').ToLowerInvariant()` plus `response.Content.ReadAsStringAsync`.","commonSituations":"Hitting Discord's global/cloudflare rate limit (429) after aggressive parallelism; Discord 5xx during an outage; malformed request triggering 400; deprecated endpoint returning an unexpected status after an API change; IP banned/temporarily blocked.","solutions":["For 429: reduce --parallel, slow down, and respect Retry-After; consider running exports sequentially.","For 5xx: check discordstatus.com and retry after a delay; these are typically transient.","For 4xx other than 401/403/404: read the Response content in the message — it usually names the invalid parameter.","Upgrade DiscordChatExporter — an unexpected status can mean Discord changed an endpoint the tool targets."],"exampleFix":"// before\ndotnet run -- exportall -g <id> -t <token> -p 10   # 10-way parallel triggers 429\n// after\ndotnet run -- exportall -g <id> -t <token> -p 1        # serialize to respect rate limits","handlingStrategy":"retry","validationCode":"// Cannot prevent server-side 5xx/429, but reduce likelihood:\n// keep --parallel low and back off on prior failures.\nif (options.Parallel > 3) options.Parallel = 3; // conservative default","typeGuard":null,"tryCatchPattern":"try { await exporter.ExportChannelAsync(req, progress, ct); }\ncatch (DiscordChatExporterException ex) when (ex.IsFatal)\n{\n    if (IsRateLimited(ex)) await Task.Delay(GetRetryAfter(ex), ct); // then retry once\n    else throw;\n}","preventionTips":["Run with low --parallel to avoid 429s.","Implement exponential backoff for 429/5xx in your wrapper.","Check discordstatus.com before large batches."],"tags":["discord-api","rate-limit","http-5xx","http-429","fatal"],"backgroundTag":null,"analyzedSha":"f6865c82167c3bfee4455da80a1f1ca5e71b95ad","analyzedAt":"2026-08-13T18:08:46.403Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}