{"record":{"id":"b91a84d85a501a0e","repo":"nodejs/node","slug":"und-err-invalid-arg-b91a84","errorCode":"UND_ERR_INVALID_ARG","errorMessage":"h2c-client: Only h2c protocol is supported","messagePattern":"h2c-client: Only h2c protocol is supported","errorType":"validation","errorClass":"InvalidArgumentError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/dispatcher/h2c-client.js","lineNumber":13,"sourceCode":"'use strict'\n\nconst { InvalidArgumentError } = require('../core/errors')\nconst Client = require('./client')\n\nclass H2CClient extends Client {\n  constructor (origin, clientOpts) {\n    if (typeof origin === 'string') {\n      origin = new URL(origin)\n    }\n\n    if (origin.protocol !== 'http:') {\n      throw new InvalidArgumentError(\n        'h2c-client: Only h2c protocol is supported'\n      )\n    }\n\n    const { maxConcurrentStreams, pipelining, ...opts } =\n            clientOpts ?? {}\n    const defaultMaxConcurrentStreams = maxConcurrentStreams ?? 100\n    let defaultPipelining = 100\n\n    if (\n      maxConcurrentStreams != null &&\n            (!Number.isInteger(maxConcurrentStreams) ||\n            maxConcurrentStreams < 1)\n    ) {\n      throw new InvalidArgumentError('maxConcurrentStreams must be a positive integer, greater than 0')\n    }\n\n    if (pipelining != null && Number.isInteger(pipelining) && pipelining > 0) {","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/dispatcher/h2c-client.js#L1-L31","documentation":"Thrown by the H2CClient constructor when the resolved origin URL protocol is not 'http:'. H2C is HTTP/2 over cleartext (RFC 8324) and is only defined for unencrypted HTTP origins; passing an https URL, or any non-http protocol, has no valid h2c semantics so the constructor rejects it.","triggerScenarios":"Constructing new H2CClient('https://example.com') or new H2CClient(new URL('ftp://...')) or omitting the scheme so URL parsing yields an unexpected protocol. The string is coerced to a URL via new URL(origin) before the protocol check, so malformed inputs that still parse with a wrong scheme also hit this.","commonSituations":"Copy-pasting an HTTPS endpoint into an h2c config; environment variable pointing at a TLS endpoint; upgrading a plain Client to H2CClient without changing the origin scheme; mixing up h2 (TLS HTTP/2) and h2c (cleartext HTTP/2).","solutions":["Use an http:// origin URL for H2CClient.","If you actually need HTTP/2 over TLS, use the regular Client with allowH2: true instead of H2CClient.","Normalize the URL before construction: strip or rewrite the scheme to http: when h2c is intended.","Validate the protocol in your config loader so misconfigured env vars fail early with a clear message."],"exampleFix":"// before\nnew H2CClient('https://internal-svc:8080')\n// after\nnew H2CClient('http://internal-svc:8080')","handlingStrategy":"validation","validationCode":"const u = typeof origin === 'string' ? new URL(origin) : origin\nif (u.protocol !== 'http:') {\n  throw new Error(`H2CClient requires an http:// origin, got ${u.protocol}`)\n}\nnew H2CClient(u)","typeGuard":"function isH2cOrigin(origin) {\n  const u = typeof origin === 'string' ? new URL(origin) : origin\n  return u instanceof URL && u.protocol === 'http:'\n}","tryCatchPattern":null,"preventionTips":["Keep h2c origins in a dedicated config section so they are visually distinct from TLS endpoints.","If TLS is needed, switch to Client with allowH2 rather than H2CClient.","Normalize URLs once at config-load time and fail fast on the wrong scheme."],"tags":["undici","h2c","http2","url","invalid-arg"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}