{"id":"b0f0b287fe75fdc7","repo":"sindresorhus/got","slug":"no-url-protocol-specified","errorCode":null,"errorMessage":"No URL protocol specified","messagePattern":"No URL protocol specified","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"source/core/utils/options-to-url.ts","lineNumber":44,"sourceCode":"\t\t\tthrow new TypeError('Parameters `path` and `pathname` are mutually exclusive.');\n\t\t}\n\n\t\tif (options.search) {\n\t\t\tthrow new TypeError('Parameters `path` and `search` are mutually exclusive.');\n\t\t}\n\n\t\tif (options.searchParams) {\n\t\t\tthrow new TypeError('Parameters `path` and `searchParams` are mutually exclusive.');\n\t\t}\n\t}\n\n\tif (options.search && options.searchParams) {\n\t\tthrow new TypeError('Parameters `search` and `searchParams` are mutually exclusive.');\n\t}\n\n\tif (!origin) {\n\t\tif (!options.protocol) {\n\t\t\tthrow new TypeError('No URL protocol specified');\n\t\t}\n\n\t\torigin = `${options.protocol}//${options.hostname ?? options.host ?? ''}`;\n\t}\n\n\tconst url = new URL(origin);\n\n\tif (options.path) {\n\t\tconst searchIndex = options.path.indexOf('?');\n\t\tif (searchIndex === -1) {\n\t\t\toptions.pathname = options.path;\n\t\t} else {\n\t\t\toptions.pathname = options.path.slice(0, searchIndex);\n\t\t\toptions.search = options.path.slice(searchIndex + 1);\n\t\t}\n\n\t\tdelete options.path;\n\t}","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/sindresorhus/got/blob/e3924aa1e53a6ca3eb93a43618ce532442a89b40/source/core/utils/options-to-url.ts#L26-L62","documentation":"options-to-url.ts:44: if no origin is supplied and `options.protocol` is unset, Got cannot construct a URL — there is no scheme to dial. The parser refuses to guess `http:` vs `https:` because guessing wrong silently breaks TLS enforcement.","triggerScenarios":"Calling Got with only a path (`got('/users')`) without a `prefixUrl` or origin, and not setting `protocol`/`hostname`. Also fires when an empty/undefined origin is passed and `protocol` is missing.","commonSituations":"Forgetting `prefixUrl` on the instance; passing a relative path where an absolute URL was expected; dynamically building URLs where the origin variable is empty in some env; misconfigured base-URL loader.","solutions":["Pass a fully-qualified URL: `got('https://api.example.com/users')`.","Or set `prefixUrl` on the instance and pass a path: `got.extend({prefixUrl: 'https://api.example.com'}).get('users')`.","If constructing dynamically, validate the origin is non-empty before calling Got.","Ensure `protocol` (e.g. `'https:'`) is set when building from parts via `hostname`/`pathname`."],"exampleFix":"// before\nawait got('/users'); // no origin, no protocol\n\n// after\nconst api = got.extend({prefixUrl: 'https://api.example.com'});\nawait api.get('users');","handlingStrategy":"validation","validationCode":"function assertResolvableUrl(origin, options) {\n  if (!origin && !options.protocol) {\n    throw new TypeError('Provide an absolute URL or set options.protocol');\n  }\n}\nassertResolvableUrl(origin, myOptions);","typeGuard":"const hasOriginOrProtocol = (origin: string, o: {protocol?: string}): boolean =>\n  Boolean(origin) || Boolean(o.protocol);","tryCatchPattern":null,"preventionTips":["Always pass an absolute URL or set `prefixUrl` on the instance.","Validate dynamic origins are non-empty before calling Got.","Set `protocol: 'https:'` when building from parts.","Centralize URL construction in a typed builder."],"tags":["url","validation","configuration"],"analyzedSha":"e3924aa1e53a6ca3eb93a43618ce532442a89b40","analyzedAt":"2026-08-03T19:22:24.770Z","schemaVersion":2}