{"record":{"id":"705915471ff975ba","repo":"reactiveui/refit","slug":"the-url-parameter-value-value-must-be-an-abs","errorCode":null,"errorMessage":"The [Url] parameter value \"{value}\" must be an absolute URI (for example \"https://host/path\").","messagePattern":"The \\[Url\\] parameter value \"(.+?)\" must be an absolute URI \\(for example \"https://host/path\"\\)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Refit/GeneratedRequestRunner.cs","lineNumber":81,"sourceCode":"        var basePath = client.BaseAddress?.AbsolutePath\n                       ?? throw new InvalidOperationException(\"BaseAddress must be set on the HttpClient instance\");\n        basePath = basePath == \"/\" ? string.Empty : basePath.TrimEnd('/');\n        var absolute = new Uri(QueryUriFormatBase, basePath + relativePath);\n        return new(absolute.GetComponents(UriComponents.PathAndQuery, queryUriFormat), UriKind.Relative);\n    }\n\n    /// <summary>Validates that a <c>[Url]</c> parameter value is an absolute URI, returning its string form as the\n    /// base for a full-URL request that bypasses the client's base address. A <see cref=\"string\"/> value is used as\n    /// written; a <see cref=\"Uri\"/> value contributes its <see cref=\"Uri.OriginalString\"/>.</summary>\n    /// <param name=\"url\">The <c>[Url]</c> parameter value: a <see cref=\"string\"/> or a <see cref=\"Uri\"/>.</param>\n    /// <returns>The absolute URI's string form.</returns>\n    /// <exception cref=\"ArgumentException\"><paramref name=\"url\"/> is <see langword=\"null\"/>, empty, or not an absolute URI.</exception>\n    public static string RequireAbsoluteUrl(object? url)\n    {\n        var text = url is Uri uri ? uri.OriginalString : url as string;\n        return Uri.TryCreate(text, UriKind.Absolute, out _)\n            ? text!\n            : throw new ArgumentException(FormatAbsoluteUrlError(url), nameof(url));\n    }\n\n    /// <summary>Builds the request path for a generated request from a template.</summary>\n    /// <param name=\"relativePathTemplate\">The method's relative path, including any leading slash and query string.</param>\n    /// <param name=\"allowUnmatchedParameter\">Whether to allow unmatched URL parameters.</param>\n    /// <param name=\"uriParams\">The replacement uri parameters, ordered by template position.</param>\n    /// <returns>A path with all the placeholder parameters in the path template replaced.</returns>\n    /// <exception cref=\"ArgumentException\">\n    /// A URI template parameter is not available in the provided parameter span and unmatched URL parameters aren't allowed.\n    /// </exception>\n    /// <remarks>Generated call sites pass the replacements as a collection expression. On C# 12 and a runtime with inline\n    /// array support (net8.0+) that materializes on the stack, so any number of path parameters is expanded without a heap\n    /// allocation; older consumers pass a small array via the same signature.</remarks>\n    public static string BuildRequestPath(\n        string relativePathTemplate,\n        bool allowUnmatchedParameter,\n        ReadOnlySpan<((int StartIdx, int EndIdx) Range, string? Value)> uriParams)\n    {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/reactiveui/refit/blob/b455f65ecc4c97d092317e349cb775f9cfc6bcdf/src/Refit/GeneratedRequestRunner.cs#L63-L99","documentation":"RequireAbsoluteUrl rejects a [Url] parameter whose value is not an absolute URI. The method accepts a string or Uri, takes the original string form, and uses Uri.TryCreate with UriKind.Absolute; any null, empty, relative, or malformed value yields an ArgumentException pointing at the offending value in the message.","triggerScenarios":"An interface method has a parameter marked [Url] and the caller passes a relative path (e.g. \"/foo\"), a scheme-less string, a null, or a Uri created with UriKind.Relative. Used to bypass the client base address, the value must carry its own scheme and host.","commonSituations":"Passing a path fragment where a full URL is expected; reading a URL from config that came back null/empty; supplying a Uri built from a relative string; dynamically building the URL and accidentally stripping the scheme.","solutions":["Pass a fully-qualified URL string such as \"https://host/api/resource\" to the [Url] parameter","If passing a Uri, construct it with UriKind.Absolute (e.g. new Uri(\"https://host/path\", UriKind.Absolute))","Validate or default the URL at the call site before invoking the method","If you meant a relative path under the base address, remove [Url] from the parameter and use the normal route template instead"],"exampleFix":"// before\nTask<Thing> GetAsync([Url] string url);\nawait api.GetAsync(\"/things/42\"); // relative => throws\n\n// after\nawait api.GetAsync(\"https://api.example.com/things/42\");","handlingStrategy":"validation","validationCode":"static string EnsureAbsoluteUrl(string url) =>\n    Uri.TryCreate(url, UriKind.Absolute, out _)\n        ? url\n        : throw new ArgumentException($\"Expected an absolute URL, got: {url}\", nameof(url));\n\nawait api.GetAsync(EnsureAbsoluteUrl(candidate));","typeGuard":"static bool IsAbsoluteUrl(string? url) =>\n    !string.IsNullOrWhiteSpace(url) && Uri.TryCreate(url, UriKind.Absolute, out _);","tryCatchPattern":"try { await api.GetAsync(url); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"must be an absolute URI\"))\n{\n    // log the bad URL and prompt the user / fall back to a configured host\n}","preventionTips":["Validate URLs at the boundary before passing them to [Url] parameters","Prefer constructing Uri with UriKind.Absolute to fail early at the source","Keep a helper that normalizes incoming strings to absolute URIs","Add unit tests covering null, empty, relative, and scheme-less inputs"],"tags":["validation","url","argument","url-parameter","argumentexception"],"backgroundTag":null,"analyzedSha":"b455f65ecc4c97d092317e349cb775f9cfc6bcdf","analyzedAt":"2026-08-13T21:20:57.878Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}