reactiveui/refit · error · ArgumentException

Unexpected parameter type in a Multipart request. Parameter

Error message

Unexpected parameter type in a Multipart request. Parameter {fieldName} is of type {parameterType}, whereas allowed types are {allowedTypes}

What it means

SerializeMultipartPart catches any exception from the configured IHttpContentSerializer.ToHttpContent and rethrows it as an ArgumentException, reporting the field name, the runtime type of the value, and the allowed types. It is a wrapper that surfaces an inner serializer failure with a Refit-friendly message.

Source

Thrown at src/Refit/GeneratedRequestRunner.cs:580

    /// <summary>Serializes a multipart part through the content serializer, wrapping a failure with the same descriptive
    /// argument exception the reflection request builder raises for an unserializable part.</summary>
    /// <typeparam name="T">The declared part type.</typeparam>
    /// <param name="settings">The Refit settings to use.</param>
    /// <param name="value">The part value to serialize.</param>
    /// <param name="fieldName">The multipart field name, named in the failure message.</param>
    /// <returns>The serialized HTTP content.</returns>
    /// <exception cref="ArgumentException">The content serializer could not serialize the value.</exception>
    public static HttpContent SerializeMultipartPart<T>(RefitSettings settings, T value, string fieldName)
    {
        try
        {
            return settings.ContentSerializer.ToHttpContent(value);
        }
        catch (Exception ex)
        {
            var parameterType = value?.GetType().Name;
            const string allowedTypes = "String, Stream, FileInfo, Byte array and anything that's JSON serializable";
            throw new ArgumentException(
                $"Unexpected parameter type in a Multipart request. Parameter {fieldName} is of type {parameterType}, whereas allowed types are {allowedTypes}",
                nameof(value),
                ex);
        }
    }

    /// <summary>Determines whether the body should use the legacy JSON enum member.</summary>
    /// <param name="serializationMethod">The body serialization method.</param>
    /// <returns><see langword="true"/> for the legacy JSON value.</returns>
    /// <remarks>Compares the underlying value so callers never name the obsolete member and raise CS0618.</remarks>
    internal static bool IsObsoleteJsonSerializationMethod(BodySerializationMethod serializationMethod) =>
        (int)serializationMethod == ObsoleteJsonBodySerializationMethodValue;

    /// <summary>Resolves the single-character delimiter for a non-multi collection format.</summary>
    /// <param name="collectionFormat">The collection format.</param>
    /// <returns>The delimiter character.</returns>
    internal static char CollectionDelimiter(CollectionFormat collectionFormat) =>
        collectionFormat switch

View on GitHub (pinned to b455f65ecc)

Solutions

  1. Pass one of the supported types: String, Stream, FileInfo, byte[], or a JSON-serializable object
  2. If the value is a complex type, make it JSON-serializable (public settable props, no cycles, supported converters)
  3. Inspect the inner exception (ex.InnerException) to find the real serialization error and address that
  4. Register a custom JsonConverter for the type or use a different IHttpContentSerializer that supports it

Example fix

// before
Task PostAsync([Body(BodySerializationMethod.UrlEncoded)] MultiPartPart part);
multipart.Add(new MultipartPart { File = someNonSerializableObject }); // serializer throws => wrapped

// after
multipart.Add(Encoding.UTF8.GetBytes(jsonString), "payload"); // byte[] is allowed
// or pass a JSON-serializable DTO with public properties
Defensive patterns

Strategy: try-catch

Validate before calling

static bool IsMultipartSupported<T>(T value) =>
    value is string or Stream or FileInfo or byte[];

if (!IsMultipartSupported(part))
    // ensure the DTO is JSON-serializable before adding it
    _ = JsonSerializer.SerializeToUtf8Bytes(part); // throws early with a clearer error
multipart.Add(part, fieldName);

Type guard

static bool IsMultipartAllowedType(object? value) =>
    value is string or Stream or FileInfo or byte[];

Try / catch

try { await api.UploadAsync(parts); }
catch (ArgumentException ex) when (ex.Message.Contains("Unexpected parameter type in a Multipart request"))
{
    var serializerError = ex.InnerException?.Message ?? ex.Message;
    logger.LogError("Multipart serialization failed: {Error}", serializerError);
}

Prevention

When it happens

Trigger: A multipart method receives an argument whose type the content serializer cannot handle. For the default SystemTextJsonContentSerializer this means a type that fails JSON serialization; for other serializers it means whatever they reject. The exception is thrown while building the multipart body, before the request is sent.

Common situations: Posting a complex object with circular references or non-serializable members in a multipart part; passing a type with no public serializable members; a custom IHttpContentSerializer that throws on a given type; a value whose JSON converter throws (e.g. unsupported polymorphism).

Related errors


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