{"record":{"id":"dc7cf1d05bef1c7f","repo":"paperclipai/paperclip","slug":"hostname-is-required","errorCode":null,"errorMessage":"Hostname is required","messagePattern":"Hostname is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/config/hostnames.ts","lineNumber":4,"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);","sourceCodeStart":1,"sourceCodeEnd":22,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/config/hostnames.ts#L1-L22","documentation":"Thrown by normalizeHostnameInput when the trimmed input is empty. The function is the canonical hostname normalizer used by hostname/allowed-hosts configuration; it trims then rejects zero-length input before attempting URL parsing. parseHostnameCsv calls it per comma-separated part, so a stray comma or blank segment in a CSV also triggers this.","triggerScenarios":"Calling normalizeHostnameInput(''), normalizeHostnameInput('   '), or parseHostnameCsv with a CSV containing an empty segment like 'host1,,host2'.","commonSituations":"A developer passes an empty string from an env var (e.g. PAPERCLIP_HOSTNAME unset yields ''). Or a config form submits a blank hostname field. Or a CSV with trailing/leading/double commas.","solutions":["Provide a non-empty hostname string after trimming.","If using parseHostnameCsv, sanitize the CSV to remove empty segments first (filter(Boolean)).","Guard callers to skip hostname normalization when the input is meant to be optional."],"exampleFix":"// before\nconst h = normalizeHostnameInput(process.env.HOST ?? '');\n// after\nconst raw = (process.env.HOST ?? '').trim();\nif (!raw) throw new Error('HOST env var is required');\nconst h = normalizeHostnameInput(raw);","handlingStrategy":"validation","validationCode":"function requireHostname(raw: string): string {\n  const trimmed = raw.trim();\n  if (!trimmed) {\n    throw new Error(\"Hostname is required\");\n  }\n  return trimmed;\n}\n\n// for CSV inputs, drop empty segments before normalizing:\nfunction sanitizeHostnameCsv(raw: string): string[] {\n  return Array.from(new Set(\n    raw.split(\",\").map((p) => p.trim()).filter(Boolean),\n  ));\n}","typeGuard":"function isNonEmptyHostname(raw: string): boolean {\n  return raw.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Trim and reject empty strings at the form/env-var boundary before calling normalizeHostnameInput.","For CSV inputs, filter out empty segments to avoid stray commas tripping the empty-hostname check."],"tags":["config","hostname","validation"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}