reactiveui/refit · error · ArgumentException

Content must be an 'application/problem+json' compliant json

Error message

Content must be an 'application/problem+json' compliant json string.

What it means

ValidationApiException.CreateCore throws ArgumentException when the source ApiException.Content is null, empty, or whitespace, because an RFC 7807 problem-details payload cannot be parsed from blank content. On .NET 8+ it uses ArgumentException.ThrowIfNullOrWhiteSpace; otherwise it checks manually.

Source

Thrown at src/Refit/ValidationApiException.cs:122

            .ConfigureAwait(false);

        return ex;
    }

    /// <summary>Validates the exception content and builds the base validation exception.</summary>
    /// <param name="exception">The API exception to convert.</param>
    /// <returns>A new validation exception wrapping the API exception.</returns>
    /// <exception cref="ArgumentException">The content of <paramref name="exception"/> is null, empty, or whitespace, so it cannot be an 'application/problem+json' payload.</exception>
    internal static ValidationApiException CreateCore(ApiException exception)
    {
        ArgumentExceptionHelper.ThrowIfNull(exception);

#if NET8_0_OR_GREATER
        ArgumentException.ThrowIfNullOrWhiteSpace(exception.Content);
#else
        if (string.IsNullOrWhiteSpace(exception.Content))
        {
            throw new ArgumentException(
                "Content must be an 'application/problem+json' compliant json string.");
        }
#endif

        return new(exception);
    }

    /// <summary>Deserializes RFC 7807 problem details without requiring public setters on extension data.</summary>
    /// <param name="content">The JSON problem details content.</param>
    /// <returns>The deserialized problem details.</returns>
    /// <exception cref="JsonException"><paramref name="content"/> is not valid JSON, or its root value is not an object.</exception>
    internal static ProblemDetails DeserializeProblemDetails(string content)
    {
#if NET10_0_OR_GREATER
        var rootElement = JsonElement.Parse(content);
#else
        using var document = JsonDocument.Parse(content);
        var rootElement = document.RootElement;

View on GitHub (pinned to b455f65ecc)

Solutions

  1. Check exception.Content is non-blank before calling AsValidation()
  2. Verify the response Content-Type is application/problem+json before converting
  3. Handle the case where the error is not an RFC 7807 problem (use ApiException directly)
  4. Inspect the status code and only convert known validation status codes (e.g. 400/422) when content is present

Example fix

// before
try { await api.CreateAsync(payload); }
catch (ApiException ex) { var validation = ex.AsValidation(); } // throws if content is empty

// after
try { await api.CreateAsync(payload); }
catch (ApiException ex)
{
    if (!string.IsNullOrWhiteSpace(ex.Content)
        && ex.Headers.ContentType?.MediaType == "application/problem+json")
    {
        var validation = ex.AsValidation();
        // handle validation errors
    }
    else { throw; }
}
Defensive patterns

Strategy: validation

Validate before calling

static bool IsProblemDetailsCandidate(ApiException ex) =>
    !string.IsNullOrWhiteSpace(ex.Content)
    && ex.Headers.ContentType?.MediaType == "application/problem+json";

if (IsProblemDetailsCandidate(ex))
    var validation = ex.AsValidation();

Type guard

static bool HasProblemContent(ApiException ex) =>
    !string.IsNullOrWhiteSpace(ex.Content);

Try / catch

try { var validation = ex.AsValidation(); }
catch (ArgumentException ex) when (ex.Message.Contains("application/problem+json"))
{
    // no body to parse; handle as a generic ApiException
}

Prevention

When it happens

Trigger: Calling ApiException.AsValidation() (which routes to CreateCore) on an exception whose HTTP response had no body, or whose body was empty/whitespace (e.g. a 400 with no content, or a server that returns headers only).

Common situations: Treating every non-2xx as a validation error without first checking for a body; a gateway/proxy stripping the body; a server returning 400 with an empty response for non-validation errors; networking layer truncating the response.

Related errors


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