reactiveui/refit · error · InvalidOperationException
The character set provided in ContentType is invalid.
Error message
The character set provided in ContentType is invalid.
What it means
The Newtonsoft.Json content serializer reads the charset from a response's Content-Type header and tries Encoding.GetEncoding(charset) after stripping one pair of surrounding quotes. When the platform cannot resolve that charset, the underlying ArgumentException is caught and rethrown as InvalidOperationException. It is a runtime, per-response error driven entirely by what the server sent.
Source
Thrown at src/Refit.Newtonsoft.Json/NewtonsoftJsonContentSerializer.cs:172
{
var charset = content.Headers.ContentType?.CharSet;
if (charset is null)
{
return null;
}
try
{
if (charset.Length > QuotePairLength && charset[0] == '"' && charset[^1] == '"')
{
charset = charset.Substring(1, charset.Length - QuotePairLength);
}
return Encoding.GetEncoding(charset);
}
catch (ArgumentException e)
{
throw new InvalidOperationException("The character set provided in ContentType is invalid.", e);
}
}
}
View on GitHub (pinned to b455f65ecc)
Solutions
- Wrap response calls in try/catch and, on this exception, re-read the content as the bytes/string and decode with a known Encoding (e.g. Encoding.UTF8) ignoring the header.
- Intercept the response in a DelegatingHandler and rewrite/normalize Content-Type charset before deserialization.
- If the charset is legitimate (e.g. a code-page) register the encoding provider at startup: Encoding.RegisterProvider(CodePagesEncodingProvider.Instance).
- Switch to Refit.SystemTextJson if Newtonsoft charset handling is not required.
Example fix
// before
var result = await api.GetUserAsync(id); // throws on bad charset
// after
UserDto result;
try {
result = await api.GetUserAsync(id);
} catch (InvalidOperationException ex) when (ex.Message.Contains("character set")) {
// re-fetch and decode ignoring the header charset
using var raw = await client.GetAsync($"/users/{id}");
var body = await raw.Content.ReadAsByteArrayAsync();
result = JsonConvert.DeserializeObject<UserDto>(Encoding.UTF8.GetString(body));
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate a charset string before relying on it (if you read it yourself).
static bool IsKnownCharset(string? charset) {
if (string.IsNullOrWhiteSpace(charset)) return true;
try { Encoding.GetEncoding(charset.Trim('"')); return true; }
catch { return false; }
} Try / catch
try {
return await api.GetThingAsync(id);
}
catch (InvalidOperationException ex) when (ex.InnerException is ArgumentException && ex.Message.Contains("character set")) {
// Re-read bytes and decode with a known encoding, ignoring the bad header.
} Prevention
- Register encoding providers at startup: Encoding.RegisterProvider(CodePagesEncodingProvider.Instance).
- Normalize Content-Type charset in a DelegatingHandler before deserialization.
- Consider Refit.SystemTextJson if you do not need Newtonsoft charset parsing.
When it happens
Trigger: A response arrives with a Content-Type charset that is malformed or unregistered, e.g. 'charset=utf-8-sig', 'charset="utf-8' (unbalanced quote), a vendor label, or a charset absent from the running .NET runtime's registered encodings.
Common situations: A third-party/legacy server emits a non-standard charset; a CDN rewrites headers; a misconfigured reverse proxy injects charset; running on a trimmed AOT build where the encoding provider for the charset was not registered.
Related errors
- Unexpected parameter type in a Multipart request. Parameter
- Sequence contains more than one matching element
- Sequence contains no matching element
- targetInterface must be an Interface
- Method must be defined and have an HTTP Method attribute
AI-assisted analysis of reactiveui/refit@b455f65ecc (2026-08-13).
Data as JSON: /api/errors/d29d9be5fc5dbb0c.
Report an issue: GitHub.