{"record":{"id":"78f45ae9a9748414","repo":"nodejs/node","slug":"proxy-url-must-use-socks5-or-socks-protocol","errorCode":null,"errorMessage":"Proxy URL must use socks5:// or socks:// protocol","messagePattern":"Proxy URL must use socks5:// or socks:// protocol","errorType":"exception","errorClass":"InvalidArgumentError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/dispatcher/socks5-proxy-agent.js","lineNumber":51,"sourceCode":"\n    // Emit experimental warning only once\n    if (!experimentalWarningEmitted) {\n      process.emitWarning(\n        'SOCKS5 proxy support is experimental and subject to change',\n        'ExperimentalWarning'\n      )\n      experimentalWarningEmitted = true\n    }\n\n    if (!proxyUrl) {\n      throw new InvalidArgumentError('Proxy URL is mandatory')\n    }\n\n    // Parse proxy URL\n    const url = typeof proxyUrl === 'string' ? new URL(proxyUrl) : proxyUrl\n\n    if (url.protocol !== 'socks5:' && url.protocol !== 'socks:') {\n      throw new InvalidArgumentError('Proxy URL must use socks5:// or socks:// protocol')\n    }\n\n    this[kProxyUrl] = url\n    this[kProxyHeaders] = options.headers || {}\n    this[kProxyProtocol] = options.proxyTls ? 'https:' : 'http:'\n    this[kRequestTls] = options.requestTls\n\n    // Extract auth from URL or options\n    this[kProxyAuth] = {\n      username: options.username || (url.username ? decodeURIComponent(url.username) : null),\n      password: options.password || (url.password ? decodeURIComponent(url.password) : null)\n    }\n\n    // Create connector for proxy connection\n    this[kConnector] = options.connect || buildConnector({\n      ...options.proxyTls,\n      servername: options.proxyTls?.servername || url.hostname\n    })","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/dispatcher/socks5-proxy-agent.js#L33-L69","documentation":"Thrown by the SOCKS5ProxyAgent constructor when the parsed proxy URL's protocol is neither 'socks5:' nor 'socks:'. The agent only speaks SOCKS5, so http://, https://, socks4:, or any other scheme is rejected after the URL is parsed. The string-or-URL input is normalized to a URL before the check.","triggerScenarios":"Passing 'http://proxy:1080' or 'socks4://proxy' to SOCKS5ProxyAgent; passing a URL instance with the wrong protocol; a typo'd scheme like 'socks5://' vs 'sock5://'.","commonSituations":"Reusing an HTTP_PROXY value for SOCKS config; copy-paste between ProxyAgent and SOCKS5ProxyAgent; env var pointing at a non-SOCKS endpoint; confusion between socks4 and socks5.","solutions":["Use a socks5:// or socks:// URL for SOCKS5ProxyAgent.","If the endpoint is an HTTP proxy, use ProxyAgent instead.","Validate the URL protocol in your config loader before constructing the agent.","Normalize env-provided URLs to the expected scheme."],"exampleFix":"// before\nnew SOCKS5ProxyAgent(process.env.HTTP_PROXY) // 'http://...'\n// after\nnew SOCKS5ProxyAgent('socks5://proxy.internal:1080')","handlingStrategy":"validation","validationCode":"const u = typeof proxyUrl === 'string' ? new URL(proxyUrl) : proxyUrl\nif (u.protocol !== 'socks5:' && u.protocol !== 'socks:') {\n  throw new Error(`SOCKS5ProxyAgent requires socks5:// or socks://, got ${u.protocol}`)\n}\nnew SOCKS5ProxyAgent(u)","typeGuard":"function isSocksUrl(origin) {\n  const u = typeof origin === 'string' ? new URL(origin) : origin\n  return u instanceof URL && (u.protocol === 'socks5:' || u.protocol === 'socks:')\n}","tryCatchPattern":null,"preventionTips":["Keep SOCKS URLs in a dedicated config section separate from HTTP proxies.","Use ProxyAgent for http/https proxies, SOCKS5ProxyAgent only for socks5/socks.","Validate the protocol at config-load time."],"tags":["undici","proxy","socks5","url","invalid-arg"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}