reactiveui/refit · error · ArgumentException

Only one parameter can be a HeaderCollection parameter

Error message

Only one parameter can be a HeaderCollection parameter

What it means

Refit permits at most one header-collection parameter per method because it needs a single target to assign the header dictionary to. The loop tracks the first header-collection index and throws if it finds a second one.

Source

Thrown at src/Refit.Reflection/RestMethodInfoInternal.AttributeReading.cs:136

        for (var i = 0; i < parameterArray.Length; i++)
        {
            if (sets[i].HeaderCollection is null)
            {
                continue;
            }

            // Opted for IDictionary<string, string> semantics here as opposed to the looser
            // IEnumerable<KeyValuePair<string, string>> because IDictionary enforces unique keys.
            if (!parameterArray[i].ParameterType.IsAssignableFrom(typeof(IDictionary<string, string>)))
            {
                throw new ArgumentException(
                    $"HeaderCollection parameter of type {parameterArray[i].ParameterType.Name} is not assignable from IDictionary<string, string>");
            }

            // Throw if there is already a HeaderCollection parameter.
            if (headerIndex >= 0)
            {
                throw new ArgumentException("Only one parameter can be a HeaderCollection parameter");
            }

            headerIndex = i;
        }

        return headerIndex;
    }

    /// <summary>Builds the map of parameter indexes to request property keys.</summary>
    /// <param name="parameterArray">The array of method parameters.</param>
    /// <param name="sets">The classified attribute set for each parameter.</param>
    /// <returns>A map of parameter indexes to property keys.</returns>
    internal static Dictionary<int, string> BuildRequestPropertyMap(ParameterInfo[] parameterArray, ParameterAttributeSet[] sets)
    {
        Dictionary<int, string>? propertyMap = null;

        for (var i = 0; i < parameterArray.Length; i++)
        {

View on GitHub (pinned to b455f65ecc)

Solutions

  1. Merge multiple header-collection parameters into a single IDictionary<string,string>.
  2. If you need individual headers, use single [Header("name")] string parameters instead of a second collection.

Example fix

// before
[Get("/x")] Task GetAsync([HeaderCollection] IDictionary<string,string> a,
                        [HeaderCollection] IDictionary<string,string> b);

// after
[Get("/x")] Task GetAsync([HeaderCollection] IDictionary<string,string> all);
// caller merges: all = new[] { a, b }.SelectMany(d => d).ToDictionary(...)
Defensive patterns

Strategy: validation

Validate before calling

static void AssertSingleHeaderCollection(MethodInfo m) {
    var count = m.GetParameters().Count(p => /* has header-collection attribute */ false);
    if (count > 1) throw new InvalidOperationException("Multiple header-collection params on " + m.Name);
}

Prevention

When it happens

Trigger: Two (or more) parameters on the same Refit interface method are both bound as header collections.

Common situations: Copy-pasting a header parameter into a second argument; combining an inherited header-collection param with a new one; refactor merging header params.

Related errors


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