reactiveui/refit · error · ArgumentException

A [Url] method must not also declare a path template; [Url]

Error message

A [Url] method must not also declare a path template; [Url] provides the full absolute URI, but the template was "{relativePath}".

What it means

A method that declares a [Url] parameter (which supplies the full absolute request URI) must not also declare a path template, because the two would conflict over what the request URL is. The guard allows an empty or '/' template only; anything else throws.

Source

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

    }

    /// <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>
    internal static int ResolveUrlParameter(ParameterInfo[] parameterArray, ParameterAttributeSet[] sets, string relativePath)
    {
        var urlIndex = FindUrlParameter(parameterArray, sets);
        if (urlIndex >= 0
            && !string.IsNullOrEmpty(relativePath)
            && relativePath != "/")
        {
            throw new ArgumentException(
                $"A [Url] method must not also declare a path template; [Url] provides the full absolute URI, but the template was \"{relativePath}\".");
        }

        return urlIndex;
    }

    /// <summary>Finds the index of the <c>[Url]</c> parameter that supplies the absolute request URI.</summary>
    /// <param name="parameterArray">The array of method parameters.</param>
    /// <param name="sets">The classified attribute set for each parameter.</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>, or the parameter is not a
    /// <see cref="string"/> or <see cref="Uri"/>.</exception>
    internal static int FindUrlParameter(ParameterInfo[] parameterArray, ParameterAttributeSet[] sets)
    {
        var urlIndex = -1;

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

View on GitHub (pinned to b455f65ecc)

Solutions

  1. Remove the path template (use [Get("")] or [Get("/")] or an empty route) when using [Url].
  2. If you need a relative path, drop [Url] and configure the base URL on the client/RefitSettings instead.

Example fix

// before
[Get("/items/{id}")] Task GetAsync([Url] string url, int id);

// after
[Get("")] Task GetAsync([Url] string url);
Defensive patterns

Strategy: validation

Validate before calling

static void AssertUrlHasNoTemplate(MethodInfo m) {
    var hasUrl = m.GetParameters().Any(p => p.GetCustomAttribute<UrlAttribute>() is not null);
    var attr = m.GetCustomAttribute<HttpMethodAttribute>();
    if (hasUrl && !string.IsNullOrEmpty(attr?.Path) && attr.Path != "/")
        throw new InvalidOperationException("[Url] method must not also declare a path template.");
}

Prevention

When it happens

Trigger: An interface method has both [Url] on a parameter and a non-empty, non-'/' path such as [Get("/items/{id}")].

Common situations: Adding a per-call base-URL parameter to a method that already had a route template; converting a fixed-URL method to [Url] without clearing the template.

Related errors


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