{"id":"c41d43dca23a0a4c","repo":"sindresorhus/got","slug":"the-url-option-must-be-relative-when-allowabsol","errorCode":null,"errorMessage":"The `url` option must be relative when `allowAbsoluteUrls` is false and `prefixUrl` is set","messagePattern":"The `url` option must be relative when `allowAbsoluteUrls` is false and `prefixUrl` is set","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"source/core/options.ts","lineNumber":1049,"sourceCode":"\treturn result;\n};\n\nconst assertRelativeUrlIfNeeded = (options: Options, url: string | URL): void => {\n\tif (!options.prefixUrl || options.allowAbsoluteUrls) {\n\t\treturn;\n\t}\n\n\tconst normalizedUrl = is.string(url) ? stripLeadingC0ControlOrSpace(removeAsciiTabOrNewline(url)) : url;\n\n\tconst isDisallowed = isAbsoluteUrl(normalizedUrl)\n\t\t|| (is.string(normalizedUrl) && (\n\t\t\thasHttpProtocolWithoutSlashes(normalizedUrl)\n\t\t\t|| startsWithSchemeRelativeSeparators(normalizedUrl)\n\t\t\t|| (options.enableUnixSockets && hasUnixProtocolWithoutSlashes(normalizedUrl))\n\t\t));\n\n\tif (isDisallowed) {\n\t\tthrow new Error('The `url` option must be relative when `allowAbsoluteUrls` is false and `prefixUrl` is set');\n\t}\n};\n\nexport const assertUrlHasSameOriginAsPrefixUrlIfNeeded = (options: Options, url: URL): void => {\n\tif (!options.prefixUrl || options.allowAbsoluteUrls) {\n\t\treturn;\n\t}\n\n\tlet prefixUrl: URL;\n\n\ttry {\n\t\tprefixUrl = new URL(options.prefixUrl);\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (isSameOrigin(prefixUrl, url)) {\n\t\treturn;","sourceCodeStart":1031,"sourceCodeEnd":1067,"githubUrl":"https://github.com/sindresorhus/got/blob/e3924aa1e53a6ca3eb93a43618ce532442a89b40/source/core/options.ts#L1031-L1067","documentation":"Thrown at source/core/options.ts:1049 by `assertRelativeUrlIfNeeded`. When `prefixUrl` is set and `allowAbsoluteUrls` is false (the new default in recent got versions), the per-call URL MUST be relative. The check detects any absolute URL form — `https://...`, scheme-relative `//...`, `http:`, and (when enabled) unix-socket protocols without leading slashes. If the URL would bypass prefixUrl by being absolute, got throws rather than silently letting the call hit a different host than the configured one.","triggerScenarios":"Calling `client('https://other-host/path')` on a got instance created with `got.extend({ prefixUrl: 'https://api.example.com' })` without opting into absolute URLs; passing `//cdn.example.com/asset` (scheme-relative); passing `http://localhost` while prefixUrl points at production.","commonSituations":"got v12→v13/v14 upgrade where `allowAbsoluteUrls` flipped to false; mixing absolute CDN URLs into a prefixed API client; copy-pasting a fully-qualified URL into a call site that previously took a path; security-hardened clients that intentionally disallow cross-origin jumps.","solutions":["Pass a relative path instead: `client('/users/1')` or `client('users/1')`.","If you intentionally need absolute URLs on this instance, opt in via `got.extend({ prefixUrl, allowAbsoluteUrls: true })`.","Use a separate non-prefixed got instance for absolute URLs to different hosts."],"exampleFix":"// before\nconst api = got.extend({ prefixUrl: 'https://api.example.com' });\nawait api('https://api.example.com/users'); // throws\n\n// after — relative path under prefix\nconst api = got.extend({ prefixUrl: 'https://api.example.com' });\nawait api('users'); // → https://api.example.com/users\n\n// or explicitly allow absolute\nconst client = got.extend({ prefixUrl: 'https://api.example.com', allowAbsoluteUrls: true });","handlingStrategy":"validation","validationCode":"function assertRelativeWhenPrefixed(prefixUrl, allowAbsoluteUrls, url) {\n  if (!prefixUrl || allowAbsoluteUrls) return;\n  if (typeof url !== 'string') return;\n  if (/^https?:\\/\\//i.test(url) || url.startsWith('//')) {\n    throw new Error('Pass a relative URL when prefixUrl is set, or set allowAbsoluteUrls: true');\n  }\n}\nassertRelativeWhenPrefixed(client.defaults.options.prefixUrl, client.defaults.options.allowAbsoluteUrls, url);\nawait client(url);","typeGuard":"function isAbsoluteUrl(url: string | URL): boolean {\n  if (url instanceof URL) return true;\n  return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith('//');\n}\n\nfunction isRelativeUrl(url: string | URL): boolean {\n  return !isAbsoluteUrl(url);\n}","tryCatchPattern":"try {\n  await client(url);\n} catch (error) {\n  if (error instanceof Error && /url option must be relative when `allowAbsoluteUrls` is false/.test(error.message)) {\n    // strip the origin if it matches prefixUrl, otherwise switch instances\n    const stripped = url.replace(new URL(client.defaults.options.prefixUrl).origin, '');\n    return client(stripped);\n  }\n  throw error;\n}","preventionTips":["Pass relative paths to prefixed got instances (`client('users')`).","Set `allowAbsoluteUrls: true` on extend() if you intentionally mix absolute URLs.","Use separate non-prefixed instances for absolute URLs to other hosts."],"tags":["url","prefix-url","configuration","security","breaking-change"],"analyzedSha":"e3924aa1e53a6ca3eb93a43618ce532442a89b40","analyzedAt":"2026-08-03T19:22:24.770Z","schemaVersion":2}