Tyrrrz/DiscordChatExporter · error · DiscordChatExporterException
Request to '{url}' failed: {response.StatusCode.ToString().S
Error message
Request to '{url}' failed: {response.StatusCode.ToString().SeparateWords(' ').ToLowerInvariant()}.
Response content: {await response.Content.ReadAsStringAsync(cancellationToken)} What it means
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.
Source
Thrown at DiscordChatExporter.Core/Discord/DiscordClient.cs:158
if (!response.IsSuccessStatusCode)
{
throw response.StatusCode switch
{
HttpStatusCode.Unauthorized => throw new DiscordChatExporterException(
"Authentication token is invalid.",
true
),
HttpStatusCode.Forbidden => throw new DiscordChatExporterException(
$"Request to '{url}' failed: forbidden."
),
HttpStatusCode.NotFound => throw new DiscordChatExporterException(
$"Request to '{url}' failed: not found."
),
_ => throw new DiscordChatExporterException(
$"""
Request to '{url}' failed: {response
.StatusCode.ToString()
.SeparateWords(' ')
.ToLowerInvariant()}.
Response content: {await response.Content.ReadAsStringAsync(
cancellationToken
)}
""",
true
),
};
}
return await response.Content.ReadAsJsonAsync(cancellationToken);
}
private async ValueTask<JsonElement?> TryGetJsonResponseAsync(View on GitHub (pinned to f6865c8216)
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.
Example fix
// before dotnet run -- exportall -g <id> -t <token> -p 10 # 10-way parallel triggers 429 // after dotnet run -- exportall -g <id> -t <token> -p 1 # serialize to respect rate limits
Defensive patterns
Strategy: retry
Validate before calling
// Cannot prevent server-side 5xx/429, but reduce likelihood: // keep --parallel low and back off on prior failures. if (options.Parallel > 3) options.Parallel = 3; // conservative default
Try / catch
try { await exporter.ExportChannelAsync(req, progress, ct); }
catch (DiscordChatExporterException ex) when (ex.IsFatal)
{
if (IsRateLimited(ex)) await Task.Delay(GetRetryAfter(ex), ct); // then retry once
else throw;
} Prevention
- Run with low --parallel to avoid 429s.
- Implement exponential backoff for 429/5xx in your wrapper.
- Check discordstatus.com before large batches.
When it happens
Trigger: 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`.
Common situations: 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.
Related errors
- Authentication token is invalid.
- Request to '{url}' failed: forbidden.
- Request to '{url}' failed: not found.
- Provided bot account is missing the MESSAGE_CONTENT privileg
AI-assisted analysis of Tyrrrz/DiscordChatExporter@f6865c8216 (2026-08-13).
Data as JSON: /api/errors/5510437c0be7dde7.
Report an issue: GitHub.