reactiveui/refit · error · ArgumentException

Response is successful, cannot create an ApiException.

Error message

Response is successful, cannot create an ApiException.

What it means

Thrown by ApiException.Create when the supplied HttpResponseMessage has a successful status code. ApiException represents a failure, so constructing one from a 2xx response is a programming error and is rejected at the argument-validation step before any content parsing.

Source

Thrown at src/Refit/ApiException.cs:207

    /// <param name="httpMethod">The HTTP method used to send the request.</param>
    /// <param name="response">The HTTP Response message.</param>
    /// <param name="refitSettings">Refit settings used to sent the request.</param>
    /// <param name="innerException">Add an inner exception to the <see cref="ApiException"/>.</param>
    /// <returns>A newly created <see cref="ApiException"/>.</returns>
    /// <exception cref="ArgumentException"><paramref name="response"/> carries a success status code, so there is no failure to represent.</exception>
    [SuppressMessage("Usage", "VSTHRD200:Use \"Async\" suffix for async methods", Justification = "Public API name preserved for backwards compatibility.")]
    public static Task<ApiException> Create(
        HttpRequestMessage message,
        HttpMethod httpMethod,
        HttpResponseMessage response,
        RefitSettings refitSettings,
        Exception? innerException)
    {
        ArgumentExceptionHelper.ThrowIfNull(response);

        if (response.IsSuccessStatusCode)
        {
            throw new ArgumentException("Response is successful, cannot create an ApiException.", nameof(response));
        }

        var exceptionMessage = CreateMessage(response.StatusCode, response.ReasonPhrase);
        return Create(
            exceptionMessage,
            message,
            httpMethod,
            response,
            refitSettings,
            innerException);
    }

    /// <summary>Create an instance of <see cref="ApiException"/> with a custom exception message.</summary>
    /// <param name="exceptionMessage">A custom exception message.</param>
    /// <param name="message">The HTTP Request message used to send the request.</param>
    /// <param name="httpMethod">The HTTP method used to send the request.</param>
    /// <param name="response">The HTTP Response message.</param>
    /// <param name="refitSettings">Refit settings used to send the request.</param>

View on GitHub (pinned to b455f65ecc)

Solutions

  1. Guard the call site: only invoke ApiException.Create when !response.IsSuccessStatusCode.
  2. If building exceptions in a custom handler/factory, branch on the status code first.
  3. In tests, ensure the HttpResponseMessage you feed in carries an error status (>=400).

Example fix

// before
var ex = await ApiException.Create(req, method, response, settings);

// after
if (!response.IsSuccessStatusCode)
{
    var ex = await ApiException.Create(req, method, response, settings);
    // handle error
}
Defensive patterns

Strategy: validation

Validate before calling

// Only build an ApiException for failure responses.
if (!response.IsSuccessStatusCode)
{
    var ex = await ApiException.Create(req, method, response, settings);
    // ... handle
}

Prevention

When it happens

Trigger: Calling ApiException.Create(...) (or a code path that calls it) with a response whose IsSuccessStatusCode is true. Usually this is reached indirectly — e.g. a custom HttpMessageHandler or a factory that builds an ApiException unconditionally for every response, not just failures.

Common situations: Writing custom error-handling/middleware that wraps ApiException.Create without first checking IsSuccessStatusCode; a test helper that fabricates exceptions for all responses; refactoring that changed which responses flow into the error path.

Related errors


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