sindresorhus/got · error · TypeError
Parameters `search` and `searchParams` are mutually exclusiv
Error message
Parameters `search` and `searchParams` are mutually exclusive.
What it means
options-to-url.ts:39: `search` (a raw query string like `'a=1&b=2'`) and `searchParams` (a structured object/URLSearchParams) cannot both be set. They both target `url.search`, so providing both is ambiguous; Got refuses rather than silently concatenating or overwriting.
Source
Thrown at source/core/utils/options-to-url.ts:39
];
export default function optionsToUrl(origin: string, options: URLOptions): URL {
if (options.path) {
if (options.pathname) {
throw new TypeError('Parameters `path` and `pathname` are mutually exclusive.');
}
if (options.search) {
throw new TypeError('Parameters `path` and `search` are mutually exclusive.');
}
if (options.searchParams) {
throw new TypeError('Parameters `path` and `searchParams` are mutually exclusive.');
}
}
if (options.search && options.searchParams) {
throw new TypeError('Parameters `search` and `searchParams` are mutually exclusive.');
}
if (!origin) {
if (!options.protocol) {
throw new TypeError('No URL protocol specified');
}
origin = `${options.protocol}//${options.hostname ?? options.host ?? ''}`;
}
const url = new URL(origin);
if (options.path) {
const searchIndex = options.path.indexOf('?');
if (searchIndex === -1) {
options.pathname = options.path;
} else {
options.pathname = options.path.slice(0, searchIndex);View on GitHub (pinned to e3924aa1e5)
Solutions
- Standardize on one query API — `searchParams` (structured) is preferred for new code.
- If migrating, convert legacy `search` strings to `URLSearchParams`/objects once at the boundary and drop `search`.
- Audit shared defaults to ensure they don't carry `search` while per-call code uses `searchParams`.
- Add a type that marks the two fields mutually exclusive in your own option builder.
Example fix
// before
await got(url, {search: 'a=1', searchParams: {b: 2}});
// after
await got(url, {searchParams: {a: 1, b: 2}}); Defensive patterns
Strategy: validation
Validate before calling
function assertOneQueryField(options) {
if (options.search && options.searchParams) {
throw new TypeError('pass query via search or searchParams, not both');
}
} Type guard
const queryFieldsConsistent = (o: {search?: string; searchParams?: unknown}): boolean =>
!(o.search && o.searchParams); Prevention
- Standardize on `searchParams` for structured queries.
- Convert legacy `search` strings to `URLSearchParams` once at the boundary.
- Validate option objects before calling Got.
- Unit-test the builder for the conflict.
When it happens
Trigger: Passing `{search: 'a=1', searchParams: {b: 2}}` in one options object, or merging defaults that carry `searchParams` with a call that sets `search` (or vice-versa).
Common situations: Refactoring from raw `search` strings to structured `searchParams` and leaving both fields populated; combining two example snippets; a helper that sets `search` while a caller adds `searchParams`.
Related errors
- `url` must not start with a slash
- `url` protocol must be followed by `//`
- Using UNIX domain sockets but option `enableUnixSockets` is
- Parameters `path` and `pathname` are mutually exclusive.
- Parameters `path` and `search` are mutually exclusive.
AI-assisted analysis of sindresorhus/got@e3924aa1e5 (2026-08-03).
Data as JSON: /data/errors/20f4004949274a13.json.
Report an issue: GitHub.