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&lt;Error&gt;(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

  1. Use the async equivalent: `await ex.GetContentAsAsync<T>()` instead of the synchronous method.
  2. Make your custom serializer implement ISynchronousContentDeserializer (add DeserializeFromString<T>(string)).
  3. 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

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


AI-assisted analysis of reactiveui/refit@b455f65ecc (2026-08-13). Data as JSON: /api/errors/4e6bd3d960515b9a. Report an issue: GitHub.