reactiveui/refit · error · ArgumentException
Multiple complex types found. Specify one parameter as the b
Error message
Multiple complex types found. Specify one parameter as the body using BodyAttribute
What it means
Thrown during implicit body detection for POST/PUT/PATCH when, after excluding params explicitly bound by other attributes (Body, Query, Header, Property, Url, etc.), more than one reference-type parameter remains. Refit would implicitly serialize the first such parameter as the body, but with two ambiguous complex parameters it cannot choose, so it demands you disambiguate with [Body].
Source
Thrown at src/Refit.Reflection/RestMethodInfoInternal.cs:676
var refParamIndex = -1;
for (var i = 0; i < parameterArray.Length; i++)
{
var parameter = parameterArray[i];
if (parameter.ParameterType.GetTypeInfo().IsValueType
|| parameter.ParameterType == typeof(string)
|| sets[i].Query is not null
|| sets[i].HeaderCollection is not null
|| sets[i].Property is not null
// A [Url] Uri parameter supplies the request URI, never the implicit body.
|| sets[i].Url is not null)
{
continue;
}
if (refParam is not null)
{
throw new ArgumentException(
"Multiple complex types found. Specify one parameter as the body using BodyAttribute");
}
refParam = parameter;
refParamIndex = i;
}
return refParam is null
? null
: Tuple.Create(
BodySerializationMethod.Serialized,
RefitSettings.Buffered,
refParamIndex);
}
/// <summary>Holds the parsed forms of a route parameter name extracted from a URL template.</summary>
/// <param name="RawName">The raw parameter name from the URL template.</param>
/// <param name="Name">The normalized parameter name with any round-tripping prefix removed.</param>View on GitHub (pinned to b455f65ecc)
Solutions
- Mark exactly one complex parameter with [Body] to make the body explicit.
- Annotate the non-body complex parameter with [Query] (or [AliasAs]/[HeaderCollection]) so it is excluded from body detection.
- If both truly belong in the body, merge them into a single composite DTO.
Example fix
// before (POST with two unannotated reference types) Task CreateAsync(Order order, Filter filter); // after — explicit body, filter goes to query Task CreateAsync([Body] Order order, [Query] Filter filter);
Defensive patterns
Strategy: validation
Validate before calling
// For POST/PUT/PATCH, flag ambiguous unannotated reference-type parameters.
using System.Reflection;
var bodyVerbs = new[] { "POST", "PUT", "PATCH" };
foreach (var m in typeof(IMyApi).GetMethods())
{
var attr = m.GetCustomAttribute<HttpMethodAttribute>();
if (attr is null || !bodyVerbs.Contains(attr.Method)) continue;
var complex = m.GetParameters()
.Where(p => !p.ParameterType.IsValueType && p.ParameterType != typeof(string)
&& p.GetCustomAttribute<BodyAttribute>() is null
&& p.GetCustomAttribute<QueryAttribute>() is null)
.ToList();
if (complex.Count > 1)
throw new InvalidOperationException($"{m.Name}: multiple complex params — mark one [Body] or the others [Query].");
} Prevention
- Always annotate the body parameter explicitly with [Body] on POST/PUT/PATCH when there's more than one complex parameter.
- Bind filter/options objects with [Query] so they're excluded from body detection.
- Review interface signatures during code review for unannotated complex params.
When it happens
Trigger: A POST/PUT/PATCH method with two unannotated reference-type parameters that aren't strings and aren't bound to query/header/url, e.g. `Task PostAsync(Order order, Customer customer)`. The loop finds a second refParam and throws.
Common situations: Sending a DTO plus another object (e.g. a file or nested model) without specifying which is the body; forgetting [Query] on a filter object that should go in the query string alongside a body DTO.
Related errors
- Multipart requests may not contain a Body parameter
- Only one parameter can be a Body parameter
- URL path {relativePath} must not contain CR or LF characters
- Method "{methodInfo.Name}" is invalid. All REST Methods must
AI-assisted analysis of reactiveui/refit@b455f65ecc (2026-08-13).
Data as JSON: /api/errors/d0572a9ac96582d0.
Report an issue: GitHub.