{"record":{"id":"f9e9b84991fe88d3","repo":"nexu-io/open-design","slug":"enter-a-valid-http-s-website-url","errorCode":null,"errorMessage":"Enter a valid http(s) website URL.","messagePattern":"Enter a valid http\\(s\\) website URL\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/daemon/src/brands/index.ts","lineNumber":289,"sourceCode":"  try {\n    return new URL(url).hostname.replace(/^www\\./i, '');\n  } catch {\n    return url;\n  }\n}\n\n/**\n * Reserve a brand and stand up the agent-driven extraction project. Throws on\n * an invalid URL (the route maps that to a 400). The caller navigates into the\n * returned project and auto-sends the seeded prompt to start the agent.\n */\nexport async function startBrandExtraction(\n  opts: StartBrandExtractionOptions,\n): Promise<StartBrandExtractionResult> {\n  const designMd = normalizeDesignMdInput(opts.designMd);\n  const rawUrl = (opts.url ?? '').trim();\n  const url = rawUrl ? normalizeUrl(rawUrl) : designMd ? sourceUrlForDesignMd(designMd, opts.description) : null;\n  if (rawUrl && !url) throw new Error('Enter a valid http(s) website URL.');\n  if (!url) throw new Error('Enter a valid http(s) website URL or paste a DESIGN.md.');\n  const hasWebsiteSource = /^https?:\\/\\//i.test(url);\n  const hasDesignMdSource = Boolean(designMd);\n\n  const {\n    brandsRoot,\n    projectsRoot,\n    skillsRoot,\n    db,\n    randomId = randomUUID,\n    logoFallback = ensureLogoFallback,\n    seedFallback = ensureBrandSeed,\n    imageryFallback = ensureImageryFallback,\n  } = opts;\n  const id = newBrandId(url);\n  const projectId = brandProjectId(id);\n  const conversationId = randomId();\n  const host = hostnameOf(url);","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/brands/index.ts#L271-L307","documentation":"Thrown by startBrandExtraction when the user supplied a url but normalizeUrl(rawUrl) returned null. normalizeUrl prepends https:// when no scheme is present, parses with new URL, and only accepts http/https protocols. The route handler maps this message to HTTP 400 (bad request).","triggerScenarios":"The URL is malformed ('htp://example', 'example..com'), uses an unsupported scheme ('ftp://', 'file://', 'mailto:'), contains characters that make new URL throw, or is structurally unparseable.","commonSituations":"User pastes with a typo in the scheme, trailing whitespace, missing dot, or surrounding quotes; CSV/bulk import containing malformed rows; client not trimming input.","solutions":["Trim whitespace and ensure the URL has an http or https scheme (or no scheme, which normalizeUrl will prefix).","Reject non-http(s) schemes early on the client.","Validate with new URL(value) and check protocol is http: or https: before submitting."],"exampleFix":"// before\nawait startBrandExtraction({ url: 'ftp://example.com', /* deps */ }); // throws\n\n// after\nawait startBrandExtraction({ url: 'https://example.com', /* deps */ });","handlingStrategy":"validation","validationCode":"function normalizeUrl(raw: string): string | null {\n  const trimmed = (raw ?? '').trim();\n  if (!trimmed) return null;\n  const withScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(trimmed) ? trimmed : `https://${trimmed}`;\n  let parsed: URL;\n  try { parsed = new URL(withScheme); } catch { return null; }\n  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return null;\n  return parsed.href;\n}\nconst normalized = normalizeUrl(userInput);\nif (userInput.trim() && !normalized) {\n  throw new Error('Enter a valid http(s) website URL.');\n}","typeGuard":"function isHttpUrl(raw: string): boolean {\n  try {\n    const u = new URL(/^https?:\\/\\//i.test(raw) ? raw : `https://${raw}`);\n    return u.protocol === 'http:' || u.protocol === 'https:';\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":"try {\n  await startBrandExtraction({ url: userInput, /* deps */ });\n} catch (err) {\n  if (err instanceof Error && err.message === 'Enter a valid http(s) website URL.') {\n    return badRequest('Please enter a valid http or https URL.');\n  }\n  throw err;\n}","preventionTips":["Trim user input and auto-prepend https:// on the client before submit.","Reject non-http(s) schemes (ftp, file, mailto) early.","Validate with new URL(value) on the client so malformed input never reaches the daemon."],"tags":["brands","validation","url","user-input"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}