{"record":{"id":"172f04726292f787","repo":"garrytan/gstack","slug":"invalid-proxy-url-could-not-parse","errorCode":null,"errorMessage":"invalid proxy URL — could not parse","messagePattern":"invalid proxy URL — could not parse","errorType":"validation","errorClass":"ProxyConfigError","httpStatus":null,"severity":"error","filePath":"browse/src/proxy-config.ts","lineNumber":49,"sourceCode":"  }\n}\n\n/**\n * Parse the BROWSE_PROXY_URL string and merge env-supplied creds.\n *\n * @throws ProxyConfigError on malformed URL, unsupported scheme, or\n *   ambiguous credentials (set in both URL and env).\n */\nexport function parseProxyConfig(opts: {\n  proxyUrl: string;\n  envUser?: string;\n  envPass?: string;\n}): ParsedProxyConfig {\n  let url: URL;\n  try {\n    url = new URL(opts.proxyUrl);\n  } catch {\n    throw new ProxyConfigError(\n      'expected scheme://[user:pass@]host:port',\n      `invalid proxy URL — could not parse`,\n    );\n  }\n\n  const scheme = url.protocol.replace(':', '');\n  if (scheme !== 'socks5' && scheme !== 'http' && scheme !== 'https') {\n    throw new ProxyConfigError(\n      'use socks5://, http://, or https://',\n      `unsupported proxy scheme '${scheme}'`,\n    );\n  }\n\n  if (!url.hostname) {\n    throw new ProxyConfigError(\n      'expected scheme://[user:pass@]host:port',\n      `invalid proxy URL — missing host`,\n    );","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/proxy-config.ts#L31-L67","documentation":"Thrown by parseProxyConfig when `new URL(opts.proxyUrl)` throws — the supplied proxy URL string is not parseable as a URL at all. The hint directs the user to the expected scheme://[user:pass@]host:port shape.","triggerScenarios":"Setting BROWSE_PROXY_URL or --proxy to a malformed string: missing scheme ('localhost:1080'), stray characters, unencoded spaces, or a value that is not a URL.","commonSituations":"Forgetting the scheme prefix (the most common cause — '127.0.0.1:1080' is not a valid URL without a scheme); copy-paste with trailing whitespace, quotes, or newlines; shell variable that expanded to empty or partial.","solutions":["Add the scheme: prefix with socks5://, http://, or https://","Strip stray whitespace and surrounding quotes from the value","Validate before use: `node -e \"new URL(process.argv[1])\" <url>`","If using a shell variable, guard it: `${BROWSE_PROXY_URL:?missing}`"],"exampleFix":"# before\nBROWSE_PROXY_URL=localhost:1080  # throws — no scheme\n\n# after\nBROWSE_PROXY_URL=socks5://localhost:1080","handlingStrategy":"validation","validationCode":"function isValidProxyUrl(s: string): boolean {\n  try {\n    const u = new URL(s);\n    return ['socks5:', 'http:', 'https:'].includes(u.protocol) && !!u.hostname;\n  } catch { return false; }\n}\n\nif (!isValidProxyUrl(proxyUrl)) {\n  throw new Error('proxy URL must be scheme://[user:pass@]host:port with scheme socks5|http|https');\n}","typeGuard":"function isParsableUrl(s: string): boolean {\n  try { new URL(s); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  const cfg = parseProxyConfig({ proxyUrl, envUser, envPass });\n} catch (e) {\n  if (e instanceof ProxyConfigError && /could not parse/.test(e.message)) {\n    console.error(`${e.message}. Hint: ${e.hint}`);\n  }\n  throw e;\n}","preventionTips":["Always include the scheme prefix (socks5://, http://, https://)","Trim whitespace and strip quotes from env-supplied URLs","Validate the URL with `new URL()` in your own config loader before passing it","Guard shell variables: `${BROWSE_PROXY_URL:?missing}`"],"tags":["proxy","config","url-parsing","network","proxy-config-error"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}