reactiveui/refit · error · ArgumentException

Argument list to method "{methodInfo.Name}" can only contain

Error message

Argument list to method "{methodInfo.Name}" can only contain a single CancellationToken

What it means

Refit allows exactly one CancellationToken per method, which it wires to the request so cancellation propagates. The scan records the first CancellationToken parameter and throws on the second. Two tokens would create ambiguity about which one governs the request lifetime.

Source

Thrown at src/Refit.Reflection/RestMethodInfoInternal.ParameterBinding.cs:386

    /// <summary>Finds the single cancellation token parameter for the method.</summary>
    /// <param name="methodInfo">The reflected method information.</param>
    /// <returns>The cancellation token parameter, or null when none is present.</returns>
    /// <exception cref="ArgumentException"><paramref name="methodInfo"/> declares more than one <c>CancellationToken</c> parameter.</exception>
    internal static ParameterInfo? FindCancellationTokenParameter(MethodInfo methodInfo)
    {
        var parameters = methodInfo.GetParameters();
        ParameterInfo? cancellationTokenParam = null;
        for (var i = 0; i < parameters.Length; i++)
        {
            if (!IsCancellationTokenParameter(parameters[i]))
            {
                continue;
            }

            if (cancellationTokenParam is not null)
            {
                throw new ArgumentException(
                    $"Argument list to method \"{methodInfo.Name}\" can only contain a single CancellationToken");
            }

            cancellationTokenParam = parameters[i];
        }

        return cancellationTokenParam;
    }

    /// <summary>Finds and validates the <c>[Url]</c> parameter that supplies the absolute request URI, ensuring the
    /// method does not also declare a path template.</summary>
    /// <param name="parameterArray">The array of method parameters.</param>
    /// <param name="sets">The classified attribute set for each parameter.</param>
    /// <param name="relativePath">The method's relative path template.</param>
    /// <returns>The index of the <c>[Url]</c> parameter, or a negative value when none is present.</returns>
    /// <exception cref="ArgumentException">More than one parameter carries <c>[Url]</c>, the parameter is not a
    /// <see cref="string"/> or <see cref="Uri"/>, or a <c>[Url]</c> parameter is combined with a non-empty path
    /// template.</exception>

View on GitHub (pinned to b455f65ecc)

Solutions

  1. Keep a single CancellationToken parameter (conventionally the last parameter) on the method.
  2. If two sources of cancellation exist, link them into one token before calling and pass that single token.

Example fix

// before
[Get("/x")] Task GetAsync(CancellationToken c1, CancellationToken c2);

// after
[Get("/x")] Task GetAsync(CancellationToken cts);
// caller links: using var linked = CancellationTokenSource.CreateLinkedTokenSource(c1, c2);
Defensive patterns

Strategy: validation

Validate before calling

static void AssertSingleCancellationToken(MethodInfo m) {
    var count = m.GetParameters().Count(p => p.ParameterType == typeof(System.Threading.CancellationToken));
    if (count > 1) throw new InvalidOperationException("Multiple CancellationToken params on " + m.Name);
}

Prevention

When it happens

Trigger: An interface method declares two parameters of type CancellationToken.

Common situations: Copy-paste of a CancellationToken; combining a base-interface token with a method-level token; refactor that duplicated the parameter.

Related errors


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