reactiveui/refit · error · ArgumentException
Parameter {owner.Name} matches both a parameter and nested p
Error message
Parameter {owner.Name} matches both a parameter and nested parameter on a parameter object What it means
The same parameter index is already present in the parameter map as a direct (non-object-property) binding, and the code is now trying to add an object/nested-property binding for it. Refit forbids a parameter being both a direct route binding and a nested object-property source simultaneously, because the two bindings would conflict.
Source
Thrown at src/Refit.Reflection/RestMethodInfoInternal.ParameterBinding.cs:249
/// <exception cref="ArgumentException"><paramref name="owner"/> is already bound as a route parameter in its own
/// right, so it cannot also supply a nested property.</exception>
internal static void AddObjectPropertyParameter(
ParameterInfo[] parameterInfo,
Dictionary<int, RestMethodParameterInfo> ret,
List<ParameterFragment> fragmentList,
string name,
ParameterInfo owner,
IReadOnlyList<PropertyInfo> propertyChain,
bool isOptional)
{
var parameterIndex = Array.IndexOf(parameterInfo, owner);
// If we already have this parameter, add an additional ParameterProperty.
if (ret.TryGetValue(parameterIndex, out var value2))
{
if (!value2.IsObjectPropertyParameter)
{
throw new ArgumentException(
$"Parameter {owner.Name} matches both a parameter and nested parameter on a parameter object");
}
value2.ParameterProperties.Add(new(name, propertyChain));
fragmentList.Add(
ParameterFragment.DynamicObject(parameterIndex, value2.ParameterProperties.Count - 1, isOptional));
return;
}
var restMethodParameterInfo = new RestMethodParameterInfo(true, owner);
restMethodParameterInfo.ParameterProperties.Add(new(name, propertyChain));
var idx = Array.IndexOf(parameterInfo, restMethodParameterInfo.ParameterInfo);
fragmentList.Add(ParameterFragment.DynamicObject(idx, 0, isOptional));
#if NET6_0_OR_GREATER
_ = ret.TryAdd(idx, restMethodParameterInfo);
#else
if (ret.ContainsKey(idx))View on GitHub (pinned to b455f65ecc)
Solutions
- Avoid binding the same parameter both directly and via nested properties; split into distinct parameters.
- Use [AliasAs] or separate DTOs so each placeholder has a single, unambiguous source.
- Review the parameter object's properties and remove the overlapping direct binding.
Example fix
// before
[Get("/{obj}/{obj.Name}")] Task GetAsync(MyObj obj); // obj bound twice
// after
[Get("/{id}/{name}")] Task GetAsync(string id, string name); Defensive patterns
Strategy: validation
Validate before calling
// Avoid binding the same parameter both directly and via nested property chains. // Ensure each placeholder resolves to exactly one source (param or property).
Prevention
- Do not reference one parameter object both whole and decomposed in the same template.
- Split overlapping bindings into separate, single-purpose parameters.
- Review DTO property exposure used in templates.
When it happens
Trigger: A method parameter is bound directly to a route placeholder AND the same parameter object is also referenced through a nested property chain for another placeholder, producing a double registration on the same index.
Common situations: A parameter object used both as a whole for {param} and decomposed into {param.Prop}; overlapping [AliasAs]/property bindings on a shared object; complex DTO bound multiple ways.
Related errors
- URL {relativePath} has parameter {rawName}, but no method pa
- A [Url] method must not also declare a path template; [Url]
- targetInterface must be an Interface
- Method must be defined and have an HTTP Method attribute
- MethodName exists more than once, 'parameterTypes' mut be de
AI-assisted analysis of reactiveui/refit@b455f65ecc (2026-08-13).
Data as JSON: /api/errors/35554aa3d9eca764.
Report an issue: GitHub.