{"record":{"id":"3898c18a3d66a2ee","repo":"dotnet/aspnetcore","slug":"cannot-resolve-url","errorCode":null,"errorMessage":"Cannot resolve '${url}'.","messagePattern":"Cannot resolve '(.+?)'\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/ts/signalr/src/HttpConnection.ts","lineNumber":676,"sourceCode":"            this._connectionStarted = false;\n            try {\n                if (this.onclose) {\n                    this.onclose(error);\n                }\n            } catch (e) {\n                this._logger.log(LogLevel.Error, `HttpConnection.onclose(${error}) threw error '${e}'.`);\n            }\n        }\n    }\n\n    private _resolveUrl(url: string): string {\n        // startsWith is not supported in IE\n        if (url.lastIndexOf(\"https://\", 0) === 0 || url.lastIndexOf(\"http://\", 0) === 0) {\n            return url;\n        }\n\n        if (!Platform.isBrowser) {\n            throw new Error(`Cannot resolve '${url}'.`);\n        }\n\n        // Setting the url to the href propery of an anchor tag handles normalization\n        // for us. There are 3 main cases.\n        // 1. Relative path normalization e.g \"b\" -> \"http://localhost:5000/a/b\"\n        // 2. Absolute path normalization e.g \"/a/b\" -> \"http://localhost:5000/a/b\"\n        // 3. Networkpath reference normalization e.g \"//localhost:5000/a/b\" -> \"http://localhost:5000/a/b\"\n        const aTag = window.document.createElement(\"a\");\n        aTag.href = url;\n\n        this._logger.log(LogLevel.Information, `Normalizing '${url}' to '${aTag.href}'.`);\n        return aTag.href;\n    }\n\n    private _resolveNegotiateUrl(url: string): string {\n        const negotiateUrl = new URL(url);\n\n        if (negotiateUrl.pathname.endsWith('/')) {","sourceCodeStart":658,"sourceCodeEnd":694,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/ts/signalr/src/HttpConnection.ts#L658-L694","documentation":"Thrown by HttpConnection._resolveUrl when the supplied URL is relative (does not start with `http://` or `https://`) AND `Platform.isBrowser` is false. In a browser, the library normalizes relative URLs via an anchor tag; outside the browser there is no DOM to resolve against, so a base URL cannot be inferred and the call is rejected.","triggerScenarios":"Running the signalr client in Node.js (or any non-browser runtime) and passing a relative path such as `/hub` or `hub` as the HubConnection URL. The same path works in a browser because the anchor-tag normalization path is taken, but in Node the `!Platform.isBrowser` guard fires.","commonSituations":"Server-side rendering, Electron main process, React Native, or a test runner (jsdom absent) where developers reuse a browser-style relative URL. Migrating code from browser to Node without adjusting the URL.","solutions":["Pass a fully-qualified absolute URL (including scheme and host) when running outside a browser.","Build the absolute URL from a base/host config variable rather than relying on document.location.","If a base is required, prepend it explicitly: `${origin}/hub`."],"exampleFix":"// before (Node runtime)\nnew HubConnectionBuilder().withUrl(\"/chat\").build();\n// after\nnew HubConnectionBuilder().withUrl(\"https://api.example.com/chat\").build();","handlingStrategy":"validation","validationCode":"function absoluteUrl(url: string): string {\n  if (/^https?:\\/\\//i.test(url)) return url;\n  const base = process.env.HUB_ORIGIN;\n  if (!base) throw new Error(\"Absolute URL required outside browser\");\n  return new URL(url, base).href;\n}","typeGuard":"function isAbsoluteUrl(url: string): boolean {\n  return /^https?:\\/\\//i.test(url);\n}","tryCatchPattern":null,"preventionTips":["Pass fully-qualified URLs in Node/SSR runtimes.","Source the URL from a typed config with origin + path.","Test the connection setup outside jsdom before shipping."],"tags":["url","node","environment","configuration"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}