{"record":{"id":"6bdc0308b08dc84c","repo":"reactiveui/refit","slug":"baseaddress-must-be-set-on-the-httpclient-instance","errorCode":null,"errorMessage":"BaseAddress must be set on the HttpClient instance","messagePattern":"BaseAddress must be set on the HttpClient instance","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Refit/GeneratedRequestRunner.cs","lineNumber":39,"sourceCode":"    private static readonly Uri QueryUriFormatBase = new(\"https://api\", UriKind.Absolute);\n\n    /// <summary>Builds the relative request URI for a generated request, joining the client base address with the method path.</summary>\n    /// <param name=\"client\">The HTTP client whose base address is used under legacy resolution.</param>\n    /// <param name=\"relativePath\">The method's relative path, including any leading slash and query string.</param>\n    /// <param name=\"urlResolution\">The configured URL resolution mode.</param>\n    /// <returns>A relative <see cref=\"Uri\"/> to assign to the request, which the client merges with its base address.</returns>\n    /// <exception cref=\"InvalidOperationException\">Legacy resolution is in effect and <paramref name=\"client\"/> has no base address to prefix the path with.</exception>\n    public static Uri BuildRelativeUri(HttpClient client, string relativePath, UrlResolutionMode urlResolution)\n    {\n        if (urlResolution == UrlResolutionMode.Rfc3986)\n        {\n            // Let the HttpClient merge the base address with the relative path per RFC 3986; emit the path verbatim.\n            return new(relativePath, UriKind.Relative);\n        }\n\n        RequireLeadingSlashUnderLegacy(relativePath);\n        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        return new(basePath + relativePath, UriKind.Relative);\n    }\n\n    /// <summary>Builds the relative request URI, re-encoding the whole path and query with a <c>[QueryUriFormat]</c> mode.</summary>\n    /// <param name=\"client\">The HTTP client whose base address is used under legacy resolution.</param>\n    /// <param name=\"relativePath\">The method's relative path, including any leading slash and query string.</param>\n    /// <param name=\"urlResolution\">The configured URL resolution mode.</param>\n    /// <param name=\"queryUriFormat\">The escaping mode from the method's <c>[QueryUriFormat]</c> attribute.</param>\n    /// <returns>A relative <see cref=\"Uri\"/> whose path and query are re-encoded with <paramref name=\"queryUriFormat\"/>.</returns>\n    /// <remarks>Mirrors the reflection request builder: it always assembles the path and query with the escaping query\n    /// builder, then re-encodes the whole thing through <see cref=\"Uri.GetComponents(UriComponents, UriFormat)\"/> with the\n    /// method's <c>QueryUriFormat</c> (so <see cref=\"UriFormat.Unescaped\"/> decodes it). Rfc3986 resolution ignores the\n    /// format, exactly as the reflection builder does.</remarks>\n    /// <exception cref=\"InvalidOperationException\">Legacy resolution is in effect and <paramref name=\"client\"/> has no base address to prefix the path with.</exception>\n    public static Uri BuildRelativeUri(HttpClient client, string relativePath, UrlResolutionMode urlResolution, UriFormat queryUriFormat)\n    {\n        if (urlResolution == UrlResolutionMode.Rfc3986)","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/reactiveui/refit/blob/b455f65ecc4c97d092317e349cb775f9cfc6bcdf/src/Refit/GeneratedRequestRunner.cs#L21-L57","documentation":"Thrown by BuildRelativeUri when the client runs under UrlResolutionMode.Legacy and HttpClient.BaseAddress is null. Legacy resolution prefixes the method's relative path with the client's base absolute path, so a missing base address leaves no path to prefix. This is an InvalidOperationException signaling a configuration gap, not a transient network fault.","triggerScenarios":"Configuring Refit with UrlResolutionMode.Legacy (or running on a target where legacy is the default) and calling a generated interface method on an HttpClient whose BaseAddress was never assigned. Switching from Rfc3986 to Legacy resolution on an existing client that relied solely on relative merging also triggers it.","commonSituations":"Calling RestService.ForGenerated with a bare HttpClient() (no base address); DI registering a named HttpClient without setting BaseAddress; migrating an app from an older Refit version that defaulted to legacy-style path concatenation; unit tests constructing HttpClient directly without a host.","solutions":["Set client.BaseAddress before invoking any interface method (e.g., client.BaseAddress = new Uri(\"https://api.example.com/\"))","If you pass the host through Refit, use RestService.For<T>(hostUrl) or CreateHttpClient(hostUrl, settings) so BaseAddress is assigned for you","Switch to UrlResolutionMode.Rfc3986 via RefitSettings if you intentionally merge paths yourself and have no single base host","In DI, configure the HttpClient with .ConfigureHttpClient(c => c.BaseAddress = new Uri(...)) inside AddRefitClient/AddRefitGeneratedClient"],"exampleFix":"// before\nvar client = new HttpClient();\nvar api = RestService.ForGenerated<IMyApi>(client, settings);\nawait api.GetThingsAsync(); // throws - no base address\n\n// after\nvar client = new HttpClient { BaseAddress = new Uri(\"https://api.example.com/\") };\nvar api = RestService.ForGenerated<IMyApi>(client, settings);\nawait api.GetThingsAsync();","handlingStrategy":"validation","validationCode":"if (client.BaseAddress is null)\n    throw new InvalidOperationException(\n        \"HttpClient.BaseAddress must be set before using Refit under legacy URL resolution.\");\nvar api = RestService.ForGenerated<IMyApi>(client, settings);","typeGuard":"static bool HasBaseAddress(HttpClient client) => client.BaseAddress is not null;","tryCatchPattern":"try { await api.GetAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"BaseAddress must be set\"))\n{\n    // reconfigure the client with a BaseAddress and retry, or surface a config error\n}","preventionTips":["Always construct the client via RestService.For<T>(hostUrl) or CreateHttpClient(hostUrl, settings) so BaseAddress is set","In DI, configure BaseAddress through ConfigureHttpClient in AddRefitClient/AddRefitGeneratedClient","Add a startup health check asserting client.BaseAddress is not null","Keep a single client-creation helper so BaseAddress cannot be forgotten"],"tags":["configuration","http-client","url-resolution","base-address","invalidoperation"],"backgroundTag":null,"analyzedSha":"b455f65ecc4c97d092317e349cb775f9cfc6bcdf","analyzedAt":"2026-08-13T21:20:57.878Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}