{"record":{"id":"af2ab4677fbf7118","repo":"dotnet/aspnetcore","slug":"the-uri-uri-is-not-contained-by-the-base-uri","errorCode":null,"errorMessage":"The URI '{uri}' is not contained by the base URI '{_baseUri}'.","messagePattern":"The URI '(.+?)' is not contained by the base URI '(.+?)'\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/NavigationManager.cs","lineNumber":347,"sourceCode":"            // baseUri ends with a slash), and from that we return \"something\"\n            return uri.Substring(_baseUri.OriginalString.Length);\n        }\n\n        var pathEndIndex = uri.AsSpan().IndexOfAny('#', '?');\n        var uriPathOnly = pathEndIndex < 0 ? uri : uri.AsSpan(0, pathEndIndex);\n        if (_baseUri.OriginalString.EndsWith('/') && uriPathOnly.Equals(_baseUri.OriginalString.AsSpan(0, _baseUri.OriginalString.Length - 1), StringComparison.Ordinal))\n        {\n            // Special case: for the base URI \"/something/\", if you're at\n            // \"/something\" then treat it as if you were at \"/something/\" (i.e.,\n            // with the trailing slash). It's a bit ambiguous because we don't know\n            // whether the server would return the same page whether or not the\n            // slash is present, but ASP.NET Core at least does by default when\n            // using PathBase.\n            return uri.Substring(_baseUri.OriginalString.Length - 1);\n        }\n\n        var message = $\"The URI '{uri}' is not contained by the base URI '{_baseUri}'.\";\n        throw new ArgumentException(message);\n    }\n\n    internal ReadOnlySpan<char> ToBaseRelativePath(ReadOnlySpan<char> uri)\n    {\n        if (MemoryExtensions.StartsWith(uri, _baseUri!.OriginalString.AsSpan(), StringComparison.Ordinal))\n        {\n            // The absolute URI must be of the form \"{baseUri}something\" (where\n            // baseUri ends with a slash), and from that we return \"something\"\n            return uri[_baseUri.OriginalString.Length..];\n        }\n\n        var pathEndIndex = uri.IndexOfAny('#', '?');\n        var uriPathOnly = pathEndIndex < 0 ? uri : uri[..pathEndIndex];\n        if (_baseUri.OriginalString.EndsWith('/') && MemoryExtensions.Equals(uriPathOnly, _baseUri.OriginalString.AsSpan(0, _baseUri.OriginalString.Length - 1), StringComparison.Ordinal))\n        {\n            // Special case: for the base URI \"/something/\", if you're at\n            // \"/something\" then treat it as if you were at \"/something/\" (i.e.,\n            // with the trailing slash). It's a bit ambiguous because we don't know","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/NavigationManager.cs#L329-L365","documentation":"The public ToBaseRelativePath(string) throws ArgumentException when the given absolute URI is neither prefixed by the base URI nor matches the base-without-trailing-slash special case. Blazor uses this to convert absolute URLs to relative paths for routing, so a mismatch means the URI is outside the app's base path.","triggerScenarios":"Calling ToBaseRelativePath with an absolute URI on a different host/scheme than BaseUri; BaseUri changed (e.g. behind a reverse proxy) but the URI is from the old base; path-only URI passed where an absolute URI was expected.","commonSituations":"App moved behind a different path prefix; misconfigured <base href> causing BaseUri mismatch; cross-origin links being processed by the router; reverse proxy stripping/adding path prefixes.","solutions":["Ensure the URI passed to ToBaseRelativePath is under the configured BaseUri (same scheme/host/path-prefix).","Fix the <base href> tag or BaseUri initialization to match the actual deployment path.","Handle cross-origin URIs separately instead of routing them through ToBaseRelativePath."],"exampleFix":"// before (BaseUri = http://app/subdir/)\nvar rel = navManager.ToBaseRelativePath(\"http://other-host/page\");\n\n// after\nvar rel = navManager.ToBaseRelativePath(\"http://app/subdir/page\");","handlingStrategy":"validation","validationCode":"static string SafeToBaseRelative(NavigationManager nm, string uri)\n{\n    var baseUri = nm.BaseUri;\n    if (!uri.StartsWith(baseUri, StringComparison.Ordinal))\n        throw new ArgumentException($\"{uri} is outside base {baseUri}\");\n    return nm.ToBaseRelativePath(uri);\n}","typeGuard":"static bool IsUnderBaseUri(string baseUri, string uri) =>\n    uri.StartsWith(baseUri, StringComparison.Ordinal) ||\n    (baseUri.EndsWith('/') && uri == baseUri[..^1]);","tryCatchPattern":"try { return navManager.ToBaseRelativePath(uri); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"not contained by the base URI\"))\n{ logger.LogWarning(ex, \"URI outside base path\"); return uri; }","preventionTips":["Keep BaseUri in sync with the deployed <base href>.","Validate cross-origin URIs before passing to ToBaseRelativePath.","Centralize URI normalization in a single helper."],"tags":["blazor","navigation","uri","base-path","configuration"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}