{"record":{"id":"e3504effbe17137c","repo":"headroomlabs-ai/headroom","slug":"invalid-proxyurl-proxyurl","errorCode":null,"errorMessage":"Invalid proxyUrl: \"${proxyUrl}\"","messagePattern":"Invalid proxyUrl: \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/openclaw/src/proxy-manager.ts","lineNumber":409,"sourceCode":"        encoding: \"utf8\",\n        stdio: [\"ignore\", \"pipe\", \"ignore\"],\n        timeout: 5000,\n      });\n      if (result.error || result.status !== 0) return null;\n      const prefix = (result.stdout ?? \"\").trim();\n      return prefix.length > 0 ? prefix : null;\n    } catch {\n      return null;\n    }\n  }\n}\n\n/** Parse a URL, returning the parsed object or throwing a descriptive error. */\nfunction parseProxyUrl(proxyUrl: string): URL {\n  try {\n    return new URL(proxyUrl);\n  } catch {\n    throw new Error(`Invalid proxyUrl: \"${proxyUrl}\"`);\n  }\n}\n\nexport function normalizeAndValidateProxyUrl(proxyUrl: string): string {\n  const parsed = parseProxyUrl(proxyUrl);\n\n  if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n    throw new Error(\"proxyUrl must use http:// or https://\");\n  }\n\n  if (parsed.pathname !== \"/\" || parsed.search || parsed.hash) {\n    throw new Error(\"proxyUrl must not include a path, query, or hash\");\n  }\n\n  return parsed.origin;\n}\n\n/** Returns true if the URL points to a local address (localhost or 127.0.0.1). */","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/plugins/openclaw/src/proxy-manager.ts#L391-L427","documentation":"normalizeAndValidateProxyUrl() could not parse the configured proxyUrl with the WHATWG URL constructor — the string is not a valid absolute URL at all (before any scheme/host checks happen). Typical culprits are missing scheme, stray characters, or a bare host:port.","triggerScenarios":"Passing proxyUrl values like \"localhost:8787\" (interpreted as scheme, actually invalid here), \"127.0.0.1:8787\", \"headroom proxy\", or a string with whitespace/control characters to normalizeAndValidateProxyUrl().","commonSituations":"Bare host:port copied from CLI docs; trailing newline from an env var or config file; URL assembled by string concatenation with a typo; scheme accidentally deleted during editing.","solutions":["Include the scheme: use \"http://127.0.0.1:8787\" not \"127.0.0.1:8787\"","Trim whitespace/newlines when the URL comes from env vars or config files","Sanity-check the value in a REPL: new URL(value) must not throw before passing it in"],"exampleFix":"// before\nmanager.configure({ proxyUrl: \"localhost:8787\" }); // throws\n\n// after\nmanager.configure({ proxyUrl: \"http://localhost:8787\" });","handlingStrategy":"type-guard","validationCode":"function isParseableUrl(value: string): boolean {\n  try {\n    new URL(value);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nif (!isParseableUrl(proxyUrl)) {\n  throw new Error(`proxyUrl '${proxyUrl}' is not a valid absolute URL — include the scheme, e.g. http://...`);","typeGuard":"function isValidAbsoluteUrl(value: string): value is `http://${string}` | `https://${string}` {\n  try {\n    const u = new URL(value);\n    return u.protocol === \"http:\" || u.protocol === \"https:\";\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":null,"preventionTips":["Always include the scheme (http:// or https://) — bare host:port values do not parse as URLs here","Trim env-var-derived URLs to remove stray newlines before use","Run config through normalizeAndValidateProxyUrl() at load time so bad URLs fail fast with one clear error"],"tags":["proxy","url","validation","openclaw"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}