sindresorhus/got · error · Error

Protocol "${this.protocol}" not supported. Expected "https:"

Error message

Protocol "${this.protocol}" not supported. Expected "https:"

What it means

Http2ClientRequest constructor at http2-client.ts:1048 refuses any protocol other than `https:` (unless an `h2session` is being injected, which implies the caller already has a session). HTTP/2 over cleartext (h2c) is not supported for client requests in this implementation; the protocol must be `https:`.

Source

Thrown at source/core/utils/http2-client.ts:1048

}

class Http2ClientRequest extends Writable {
	constructor(input: string | URL | NormalizedRequestOptions, options?: NormalizedRequestOptions | RequestCallback, callback?: RequestCallback) {
		super({
			autoDestroy: false,
			emitClose: false,
		});

		const normalized = normalizeInput(input, options, callback);
		this.options = normalized.options;
		this.callback = normalized.callback;
		this.method = (this.options.method ?? 'GET').toUpperCase();
		this.path = this.method === HTTP2_METHOD_CONNECT ? String(this.options.path ?? '') : String(this.options.path ?? '/');
		this.protocol = String(this.options.protocol ?? 'https:');
		this.headers = Object.create(null) as RequestHeaders;

		if (this.protocol !== 'https:' && !this.options.h2session) {
			throw new Error(`Protocol "${this.protocol}" not supported. Expected "https:"`);
		}

		const headers = this.options.headers as RequestHeaders | undefined;

		if (headers) {
			for (const [key, value] of Object.entries(headers)) {
				this.setHeader(key, value);
			}
		}

		if (this.options.auth && !this.hasHeader('authorization')) {
			this.setHeader('authorization', `Basic ${Buffer.from(this.options.auth).toString('base64')}`);
		}

		if (this.callback) {
			this.once('response', this.callback);
		}

View on GitHub (pinned to e3924aa1e5)

Solutions

  1. Use an `https://` URL when `http2: true` is set.
  2. If you must talk h2c (cleartext), use a dedicated h2c client — Got does not support it.
  3. Scope the `http2: true` default to https-only instances, or branch on the URL protocol before enabling http2.
  4. Verify `prefixUrl` / `url` literals start with `https://` when http2 is on.

Example fix

// before
await got('http://api.internal/svc', {http2: true});

// after
await got('https://api.internal/svc', {http2: true});
Defensive patterns

Strategy: validation

Validate before calling

function assertHttp2Compatible(url) {
  const protocol = new URL(url).protocol;
  if (protocol !== 'https:') {
    throw new Error(`HTTP/2 requires https:, got ${protocol}`);
  }
}
assertHttp2Compatible(url);
await got(url, {http2: true});

Type guard

const isHttpsUrl = (u: string | URL): boolean =>
  (typeof u === 'string' ? new URL(u).protocol : u.protocol) === 'https:';

Prevention

When it happens

Trigger: Calling `got('http://example.com', {http2: true})` (cleartext http URL with http2 enabled), passing a `URL` whose `.protocol === 'http:'` to the http2 path, or a config that sets `http2: true` globally but targets an http origin.

Common situations: Forgetting that HTTP/2 client support is TLS-only; pointing a default-`http2` instance at a plain-http internal service; misconfigured `prefixUrl` using `http://`; local dev against an http upstream while production is https.

Related errors


AI-assisted analysis of sindresorhus/got@e3924aa1e5 (2026-08-03). Data as JSON: /data/errors/37032dc25a764d7b.json. Report an issue: GitHub.