{"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/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/SignalR/clients/ts/signalr/src/HttpConnection.ts#L658-L694","documentation":"Thrown at HttpConnection.ts:676 inside _resolveUrl when the supplied url does not start with `http://` or `https://` AND `Platform.isBrowser` is false. Browsers can resolve relative URLs via an anchor tag (lines 684-688), but Node and other non-browser environments have no document to normalize against, so a non-absolute URL is unrecoverable.","triggerScenarios":"In Node, calling `new HttpConnection('/hubs/chat')` or `new HttpConnection('hubs/chat')` or `'localhost:5000/hub'` (missing scheme). Browser builds accept these because window.document.createElement('a') resolves them, but Node builds hit the throw at line 676.","commonSituations":"Sharing the same code/config between browser and Node (SSR, Next.js getServerSideProps, SSR-rendered React); reading a relative path from env config and using it in a Node worker; forgetting the protocol when hardcoding a localhost URL in tests.","solutions":["Pass a fully-qualified absolute URL in Node: `http://localhost:5000/hubs/chat`.","Derive the URL from a base in Node: `new URL('/hubs/chat', process.env.BASE_URL).toString()`.","For isomorphic code, branch on environment: in Node prepend the origin, in browser pass the relative path."],"exampleFix":"// before (Node throws)\nnew HttpConnection('/hubs/chat');\n\n// after\nconst base = process.env.HUB_BASE_URL || 'http://localhost:5000';\nnew HttpConnection(new URL('/hubs/chat', base).toString());","handlingStrategy":"validation","validationCode":"function toAbsoluteUrl(maybeRelative) {\n  if (/^https?:\\/\\//i.test(maybeRelative)) return maybeRelative;\n  if (typeof window !== 'undefined') return new URL(maybeRelative, window.location.href).toString();\n  throw new Error(`Cannot resolve '${maybeRelative}' outside a browser; provide an absolute URL`);\n}\nconst absUrl = toAbsoluteUrl(config.hubUrl);","typeGuard":"function isAbsoluteHttpUrl(u: string): boolean {\n  return /^https?:\\/\\//i.test(u);\n}","tryCatchPattern":"// thrown synchronously from the constructor; wrap construction\nlet conn;\ntry { conn = new HttpConnection(url, options); }\ncatch (e) {\n  if (/Cannot resolve/.test(String(e))) {\n    conn = new HttpConnection(new URL(url, process.env.BASE_URL).toString(), options);\n  } else throw e;\n}","preventionTips":["In Node/SSR always pass a fully-qualified URL with scheme.","Use new URL(rel, base) to compute absolute URLs isomorphically.","Reject empty/relative URLs in your config loader."],"tags":["url","node","environment","configuration"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}