reactiveui/refit · error · NotSupportedException
The configured content serializer '{RefitSettings.ContentSer
Error message
The configured content serializer '{RefitSettings.ContentSerializer.GetType()}' does not implement ISynchronousContentDeserializer; use GetContentAsAsync instead. What it means
Thrown by ApiException.GetContentAs<T>() when the configured IHttpContentSerializer does not implement ISynchronousContentDeserializer. GetContentAs is a synchronous API (usable in exception filters where await is illegal); only serializers that can deserialize a string synchronously can serve it. The default SystemTextJsonContentSerializer does implement it; a custom serializer may not.
Source
Thrown at src/Refit/ApiException.cs:343
/// <returns>The deserialized content, or <see langword="default"/> when there is no content.</returns>
/// <exception cref="NotSupportedException">
/// Thrown when the configured <see cref="IHttpContentSerializer"/> does not implement
/// <see cref="ISynchronousContentDeserializer"/>.
/// </exception>
[SuppressMessage(
"Design",
"SST2307:Generic method type parameters should be inferable from the parameters",
Justification = "Type parameter intentionally specified explicitly by callers.")]
public T? GetContentAs<T>()
{
if (!HasContent)
{
return default;
}
if (RefitSettings.ContentSerializer is not ISynchronousContentDeserializer synchronousDeserializer)
{
throw new NotSupportedException(
$"The configured content serializer '{RefitSettings.ContentSerializer.GetType()}' does not "
+ $"implement {nameof(ISynchronousContentDeserializer)}; use {nameof(GetContentAsAsync)} instead.");
}
return synchronousDeserializer.DeserializeFromString<T>(Content!);
}
/// <summary>
/// Attempts to synchronously deserialize the buffered response content as <typeparamref name="T"/> without
/// throwing, making it usable from an exception filter:
/// <c>catch (ApiException ex) when (ex.TryGetContentAs<Error>(out var error))</c> (#1591).
/// </summary>
/// <typeparam name="T">Type to deserialize the content to.</typeparam>
/// <param name="content">The deserialized content when this returns <see langword="true"/>; otherwise <see langword="default"/>.</param>
/// <returns>
/// <see langword="true"/> when the content was present and deserialized to a non-null value; otherwise <see langword="false"/>.
/// </returns>
[SuppressMessage(View on GitHub (pinned to b455f65ecc)
Solutions
- Use the async equivalent: `await ex.GetContentAsAsync<T>()` instead of the synchronous method.
- Make your custom serializer implement ISynchronousContentDeserializer (add DeserializeFromString<T>(string)).
- If you only need the raw string, read ex.Content (the buffered string) directly without deserialization.
Example fix
// before — custom serializer without sync deserialization var err = ex.GetContentAs<Error>(); // throws NotSupportedException // after — use the async overload var err = await ex.GetContentAsAsync<Error>(); // or implement ISynchronousContentDeserializer on your serializer to keep GetContentAs
Defensive patterns
Strategy: try-catch
Validate before calling
// Prefer the async API to avoid the capability check entirely. var err = await ex.GetContentAsAsync<T>();
Type guard
// Check the serializer capability before calling the sync overload.
static bool CanSyncDeserialize(RefitSettings s) =>
s.ContentSerializer is ISynchronousContentDeserializer; Try / catch
T? content;
if (ex.RefitSettings.ContentSerializer is ISynchronousContentDeserializer)
content = ex.GetContentAs<T>();
else
content = await ex.GetContentAsAsync<T>(); Prevention
- Default to GetContentAsAsync; reserve GetContentAs for exception filters where await is illegal.
- If you ship a custom serializer, implement ISynchronousContentDeserializer so both APIs work.
- Document in your team which serializers support synchronous deserialization.
When it happens
Trigger: Calling ex.GetContentAs<T>() while RefitSettings.ContentSerializer is a custom serializer lacking ISynchronousContentDeserializer. The is-pattern check fails and the NotSupportedException names the offending serializer type and points to GetContentAsAsync.
Common situations: Using a third-party or hand-rolled content serializer that only implements async deserialization; calling GetContentAs in a catch filter with a non-default serializer; upgrading Refit and an old custom serializer no longer satisfies the interface.
Related errors
- Unexpected parameter type in a Multipart request. Parameter
- Unexpected parameter type in a Multipart request. Parameter
- Response is successful, cannot create an ApiException.
- The HttpResponseMessage has no associated RequestMessage. Wh
- The content serializer can't be null
AI-assisted analysis of reactiveui/refit@b455f65ecc (2026-08-13).
Data as JSON: /api/errors/4e6bd3d960515b9a.
Report an issue: GitHub.