dotnet/aspnetcore · error · ArgumentException

The URI '{relativeUri}' is not a relative URI. When Relative

Error message

The URI '{relativeUri}' is not a relative URI. When RelativeToCurrentUri is true, the URI must be relative (e.g., 'page.html', 'folder/page', '../other').

What it means

Thrown by NavigationManager.ResolveRelativeToCurrentPath when NavigationOptions.RelativeToCurrentUri is true but the supplied URI is absolute (starts with '/' or parses as an absolute URI). When RelativeToCurrentUri is set, the framework resolves the path against the current URI, which only makes sense for relative references.

Source

Thrown at src/Components/Components/src/NavigationManager.cs:176

    /// (as returned by <see cref="BaseUri"/>).</param>
    /// <param name="options">Provides additional <see cref="NavigationOptions"/>.</param>
    public void NavigateTo([StringSyntax(StringSyntaxAttribute.Uri)] string uri, NavigationOptions options)
    {
        AssertInitialized();

        if (options.RelativeToCurrentUri)
        {
            uri = ResolveRelativeToCurrentPath(uri);
        }

        NavigateToCore(uri, options);
    }

    internal string ResolveRelativeToCurrentPath(string relativeUri)
    {
        if (IsAbsoluteUri(relativeUri))
        {
            throw new ArgumentException(
                $"The URI '{relativeUri}' is not a relative URI. When RelativeToCurrentUri is true, the URI must be relative (e.g., 'page.html', 'folder/page', '../other').",
                nameof(relativeUri));
        }

        var currentUri = _uri!.AsSpan();

        // fragment-only and query-only references are special cases
        // that resolve against the full current URI
        if (relativeUri.StartsWith('#'))
        {
            var existingFragmentIndex = currentUri.IndexOf('#');
            if (existingFragmentIndex >= 0)
            {
                return string.Concat(currentUri[..existingFragmentIndex], relativeUri.AsSpan());
            }
            return string.Concat(_uri, relativeUri);
        }

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Pass a relative URI (e.g. "page", "sub/page", "../other", "#frag", "?q=1") when RelativeToCurrentUri is true.
  2. Set RelativeToCurrentUri = false if you must pass an absolute or root-relative URI.
  3. Strip the scheme/host or leading slash before calling when you want path-relative resolution.

Example fix

// before
navManager.NavigateTo("https://app.com/users/42", new NavigationOptions { RelativeToCurrentUri = true });

// after
navManager.NavigateTo("users/42", new NavigationOptions { RelativeToCurrentUri = true });
Defensive patterns

Strategy: validation

Validate before calling

static bool IsRelativeForResolution(string uri) =>
    !uri.StartsWith('/') && !Uri.TryCreate(uri, UriKind.Absolute, out _);

var opts = new NavigationOptions { RelativeToCurrentUri = true };
if (opts.RelativeToCurrentUri && !IsRelativeForResolution(uri))
    throw new ArgumentException("URI must be relative when RelativeToCurrentUri is true.");

Try / catch

try { navManager.NavigateTo(uri, opts); }
catch (ArgumentException ex) when (ex.Message.Contains("not a relative URI"))
{ logger.LogWarning(ex, "Rejected absolute URI in relative mode"); }

Prevention

When it happens

Trigger: Calling NavigateTo(uri, new NavigationOptions { RelativeToCurrentUri = true }) with a fully-qualified URL like "https://host/page"; passing a site-root-relative path like "/folder/page" (leading slash counts as absolute); reusing the same URI string for both relative and absolute navigation modes.

Common situations: Mixing client-side relative links with absolute URLs generated by a backend; a toggle flag defaulting to true while the code passes absolute URIs; migration from relative to absolute URIs without updating the option.

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/b7b5d4c18e155f5b. Report an issue: GitHub.