reactiveui/refit · error · JsonException

Problem details JSON must be an object.

Error message

Problem details JSON must be an object.

What it means

DeserializeProblemDetails throws JsonException when the parsed problem-details content's root JSON value is not an object (e.g. it is an array, a bare string/number, true/false, or null). RFC 7807 problem details must be a JSON object, so any other root kind is rejected after parsing succeeds.

Source

Thrown at src/Refit/ValidationApiException.cs:144

        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;
#endif
        if (rootElement.ValueKind != JsonValueKind.Object)
        {
            throw new JsonException("Problem details JSON must be an object.");
        }

        var problemDetails = new ProblemDetails();
        foreach (var property in rootElement.EnumerateObject())
        {
            ReadProblemDetailsProperty(problemDetails, property);
        }

        return problemDetails;
    }

    /// <summary>Reads a single problem-details property.</summary>
    /// <param name="problemDetails">The problem details instance to populate.</param>
    /// <param name="property">The JSON property to read.</param>
    internal static void ReadProblemDetailsProperty(
        ProblemDetails problemDetails,
        JsonProperty property)
    {

View on GitHub (pinned to b455f65ecc)

Solutions

  1. Ensure the server returns a single RFC 7807 problem-details JSON object as the response body
  2. If the API legitimately returns arrays/scalars, deserialize with a custom handler instead of ValidationApiException
  3. Inspect the raw content and content type before attempting problem-details deserialization
  4. Wrap deserialization in a try/catch for JsonException and fall back to ApiException

Example fix

// before
var validation = ex.AsValidation(); // throws if body is e.g. [ { ... }, { ... } ]

// after
try
{
    var validation = ex.AsValidation();
}
catch (JsonException)
{
    // body is valid JSON but not a problem-details object; handle generically
    logger.LogWarning("Non-object problem body: {Body}", ex.Content);
    throw;
}
Defensive patterns

Strategy: try-catch

Validate before calling

static bool IsJsonObjectPayload(string content)
{
    using var doc = JsonDocument.Parse(content);
    return doc.RootElement.ValueKind == JsonValueKind.Object;
}

if (!string.IsNullOrWhiteSpace(ex.Content) && IsJsonObjectPayload(ex.Content))
    var validation = ex.AsValidation();

Type guard

static bool IsProblemDetailsObject(string content)
{
    try
    {
        using var doc = JsonDocument.Parse(content);
        return doc.RootElement.ValueKind == JsonValueKind.Object;
    }
    catch { return false; }
}

Try / catch

try { var validation = ex.AsValidation(); }
catch (JsonException ex) when (ex.Message.Contains("must be an object"))
{
    // body is valid JSON but not an object; handle generically as ApiException
    logger.LogWarning("Non-object problem body: {Body}", ex2.Content);
}

Prevention

When it happens

Trigger: The response body parses as valid JSON but its top-level value is not an object: a JSON array, a scalar, or a JSON null. Reached via ValidationApiException deserialization when the server returned a structurally valid but non-object payload claiming to be problem+json.

Common situations: A server returning a JSON array of errors instead of a single problem-details object; a proxy returning a scalar status; a misconfigured error formatter; version skew where the API changed its error envelope shape.

Related errors


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