sindresorhus/got · error · TypeError
HTTP/2 pseudo-headers are not supported in `options.headers`
Error message
HTTP/2 pseudo-headers are not supported in `options.headers`: ${name} What it means
Thrown at source/core/options.ts:1125 by `assertValidHeaderName`. HTTP/2 reserves header names starting with `:` (pseudo-headers like `:method`, `:path`, `:authority`, `:scheme`) — these are derived automatically by the HTTP/2 layer and must not be set by the user. The check rejects any header name beginning with `:` regardless of HTTP version, because passing such a header would either be silently dropped (HTTP/1) or conflict with the protocol's own pseudo-headers (HTTP/2).
Source
Thrown at source/core/options.ts:1125
} finally {
options.allowAbsoluteUrls = allowAbsoluteUrls;
}
}
if (username !== undefined) {
options.username = username;
}
if (password !== undefined) {
options.password = password;
}
return options.url as URL;
}
function assertValidHeaderName(name: string): void {
if (name.startsWith(':')) {
throw new TypeError(`HTTP/2 pseudo-headers are not supported in \`options.headers\`: ${name}`);
}
}
/**
Safely assign own properties from source to target, skipping `__proto__` to prevent prototype pollution from JSON.parse'd input.
*/
function safeObjectAssign<Target extends Record<string, unknown>, Source extends Record<string, unknown>>(target: Target, source: Source): void {
for (const [key, value] of Object.entries(source)) {
if (key === '__proto__') {
continue;
}
Reflect.set(target, key, value);
}
}
const isToughCookieJar = (cookieJar: PromiseCookieJar | ToughCookieJar): cookieJar is ToughCookieJar => cookieJar.setCookie.length === 4 && cookieJar.getCookieString.length === 0;
View on GitHub (pinned to e3924aa1e5)
Solutions
- Remove pseudo-headers (`:method`, `:path`, `:scheme`, `:authority`) from your headers object — they are set by the protocol.
- For the equivalent control in HTTP/1, use the corresponding options: `method`, `url`/`path`, and the `host` header.
- Filter incoming header maps before passing them: `Object.fromEntries(Object.entries(h).filter(([k]) => !k.startsWith(':')))`.
Example fix
// before
await got(url, { headers: { ':authority': 'api.example.com', 'user-agent': 'x' } });
// after — use regular headers only
await got(url, { headers: { host: 'api.example.com', 'user-agent': 'x' } });
// filter pseudo-headers from upstream source
const headers = Object.fromEntries(
Object.entries(rawHeaders).filter(([k]) => !k.startsWith(':'))
); Defensive patterns
Strategy: validation
Validate before calling
function stripPseudoHeaders(headers) {
for (const key of Object.keys(headers)) {
if (key.startsWith(':')) {
throw new TypeError(`HTTP/2 pseudo-headers are not supported in options.headers: ${key}`);
}
}
return headers;
}
await got(url, { headers: stripPseudoHeaders(headers) }); Type guard
function hasPseudoHeader(headers: Record<string, unknown>): boolean {
return Object.keys(headers).some(k => k.startsWith(':'));
} Try / catch
try {
await got(url, { headers });
} catch (error) {
if (error instanceof TypeError && /HTTP\/2 pseudo-headers are not supported/.test(error.message)) {
const cleaned = Object.fromEntries(Object.entries(headers).filter(([k]) => !k.startsWith(':')));
return got(url, { headers: cleaned });
}
throw error;
} Prevention
- Never include headers whose name starts with ':' — pseudo-headers are set by the HTTP/2 layer.
- Filter incoming header maps (e.g. from HTTP/2 traces or gRPC) before passing to got.
- Use `method`, `url`, and the `host` header instead of :method/:path/:authority.
When it happens
Trigger: Passing `headers: { ':authority': 'x' }`, `headers: { ':method': 'GET' }`, or any header key starting with a colon; programmatically building headers from a map that includes pseudo-headers; copy-pasting HTTP/2 traces into request code.
Common situations: Migrating from gRPC/HTTP2 debug traces into a got client; building headers from a generic serializer that includes pseudo-headers; tooling that surfaces `:path` as if it were a regular header.
Related errors
- Use `undefined` instead of `null` to delete the `${key}` hea
- The `${key}` header must be a single value
- Missing `url` property
- The `${options.method}` method cannot be used with a body
- Unexpected option: ${key}
AI-assisted analysis of sindresorhus/got@e3924aa1e5 (2026-08-03).
Data as JSON: /data/errors/2cf40f991ee9ac48.json.
Report an issue: GitHub.