{"record":{"id":"de2072c97c97fec0","repo":"paperclipai/paperclip","slug":"invalid-hostname-raw","errorCode":null,"errorMessage":"Invalid hostname: ${raw}","messagePattern":"Invalid hostname: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/config/hostnames.ts","lineNumber":13,"sourceCode":"export function normalizeHostnameInput(raw: string): string {\n  const input = raw.trim();\n  if (!input) {\n    throw new Error(\"Hostname is required\");\n  }\n\n  try {\n    const url = input.includes(\"://\") ? new URL(input) : new URL(`http://${input}`);\n    const hostname = url.hostname.trim().toLowerCase();\n    if (!hostname) throw new Error(\"Hostname is required\");\n    return hostname;\n  } catch {\n    throw new Error(`Invalid hostname: ${raw}`);\n  }\n}\n\nexport function parseHostnameCsv(raw: string): string[] {\n  if (!raw.trim()) return [];\n  const unique = new Set<string>();\n  for (const part of raw.split(\",\")) {\n    const hostname = normalizeHostnameInput(part);\n    unique.add(hostname);\n  }\n  return Array.from(unique);\n}\n\n","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/config/hostnames.ts#L1-L27","documentation":"Thrown by normalizeHostnameInput in the catch block when the URL constructor throws (input is non-empty but not parseable as a URL even with an http:// prefix prepended). The original raw input is included verbatim in the message for diagnosis. This is the catch-all for malformed hostname strings that never get far enough to extract a hostname.","triggerScenarios":"Calling normalizeHostnameInput with a string containing characters or structure that new URL() rejects, such as a hostname with spaces, control characters, unmatched brackets, or invalid %-encoding. Because the function prepends 'http://' when there is no scheme, inputs that already include a bad scheme also land here.","commonSituations":"A developer copies a hostname with a trailing path/query and bad characters, includes spaces, or pastes a value with stray quotes. Or mixes schemes like 'ftp://example.com' which is parseable but, combined with other bad input, throws.","solutions":["Pass a bare domain or IP, optionally with http/https scheme and port: 'example.com', 'http://example.com:8080'.","Strip paths, queries, and quotes before normalizing.","If you need to accept URLs and extract the host, pre-validate with new URL() in a try/catch and pass only .hostname."],"exampleFix":"// before\nconst h = normalizeHostnameInput('https://example.com/path?x=1 bad');\n// after\nconst h = normalizeHostnameInput('example.com');","handlingStrategy":"validation","validationCode":"function prevalidateHostname(raw: string): void {\n  const trimmed = raw.trim();\n  if (!trimmed) throw new Error(\"Hostname is required\");\n  // strip nothing; just try the same URL parse the normalizer will do\n  try {\n    const url = new URL(trimmed.includes(\"://\") ? trimmed : `http://${trimmed}`);\n    if (!url.hostname) throw new Error(`Invalid hostname: ${raw}`);\n  } catch {\n    throw new Error(`Invalid hostname: ${raw}`);\n  }\n}","typeGuard":"function isValidHostname(raw: string): boolean {\n  const trimmed = raw.trim();\n  if (!trimmed) return false;\n  try {\n    const url = new URL(trimmed.includes(\"://\") ? trimmed : `http://${trimmed}`);\n    return url.hostname.trim().length > 0;\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":null,"preventionTips":["Pass bare domains/IPs (optionally with http/https scheme and port) and avoid embedding paths, queries, or spaces.","Validate hostname strings with a URL-parse pre-check in forms before submitting to the normalizer.","URL-encode or strip stray quotes/control characters from paste sources before normalizing."],"tags":["config","hostname","validation"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}