{"record":{"id":"b155995b6d9b6d1c","repo":"jackwener/OpenCLI","slug":"invalid-component-identifier-raw-expected-aut","errorCode":null,"errorMessage":"Invalid component identifier: ${raw}. Expected author/slug.","messagePattern":"Invalid component identifier: (.+?)\\. Expected author/slug\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clis/uiverse/_shared.js","lineNumber":38,"sourceCode":"\n  let pathname = raw;\n  if (/^https?:\\/\\//i.test(raw)) {\n    const url = new URL(raw);\n    if (url.hostname !== 'uiverse.io' && url.hostname !== 'www.uiverse.io') {\n      throw new Error(`Unsupported non-Uiverse URL: ${raw}`);\n    }\n    pathname = url.pathname;\n  }\n\n  const cleaned = trimPathSegment(pathname);\n  const segments = cleaned.split('/').filter(Boolean);\n  if (segments.length !== 2) {\n    throw new Error(`Could not parse author/slug from input: ${raw}`);\n  }\n\n  const [username, slug] = segments;\n  if (!username || !slug) {\n    throw new Error(`Invalid component identifier: ${raw}. Expected author/slug.`);\n  }\n\n  return {\n    raw,\n    username,\n    slug,\n    url: `${UIVERSE_BASE_URL}/${username}/${slug}`,\n  };\n}\n\nasync function fetchJsonInBrowser(page, url) {\n  const raw = await page.evaluate(`(async () => {\n    const url = ${JSON.stringify(url)};\n    const response = await fetch(url, {\n      credentials: 'include',\n      headers: {\n        accept: 'application/json, text/plain, */*',\n      },","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/uiverse/_shared.js#L20-L56","documentation":"Thrown by parseComponentInput after the input splits into exactly two segments but one of them is empty (falsy). Since empty segments are filtered out earlier this usually indicates a slug or username made only of whitespace-stripped content after trimPathSegment, or an input like 'author/' where path trimming leaves a single empty piece — a defensive check for a malformed author/slug pair.","triggerScenarios":"Passing inputs like ' / ' or strings whose trimmed segments collapse to empty; a URL whose pathname segments are whitespace or control characters that trim away; programmatically constructed identifiers where username or slug variable was empty string and joined as '/' or 'a/'.","commonSituations":"Template strings like `${author}/${slug}` with an undefined/empty slug; stripping invalid characters from a slug down to empty string before passing it in; spreadsheet/config data with blank slug column.","solutions":["Ensure both author and slug are non-empty, e.g. 'pravsingh/sky-button'","Check upstream variables feeding the identifier (log them before calling the CLI)","Copy the identifier directly from the component page URL instead of constructing it","Sanitize source data: replace blank slugs with the real component slug"],"exampleFix":"// before\nawait getPostDetails(page, `${author}/`); // slug empty -> 'Invalid component identifier'\n// after\nif (!author || !slug) throw new Error('author and slug are both required');\nawait getPostDetails(page, `${author}/${slug}`);","handlingStrategy":"validation","validationCode":"function assertCompleteIdentifier([username, slug]) {\n  if (!username?.trim() || !slug?.trim()) throw new Error('both author and slug are required');\n}\nconst segs = input.split('/').filter(Boolean);\nassertCompleteIdentifier(segs);","typeGuard":"const isCompletePair = (v) =>\n  typeof v === 'string' && v.split('/').filter(s => s.trim()).length === 2;","tryCatchPattern":"try {\n  const details = await getPostDetails(page, input);\n} catch (e) {\n  if (e.message.startsWith('Invalid component identifier')) {\n    console.error(`Malformed identifier '${input}' — check for empty author or slug.`);\n    process.exit(2);\n  }\n  throw e;\n}","preventionTips":["Check template-string sources: undefined variables produce 'undefined/' style garbage identifiers","Sanitize slugs from external data (spreadsheets, DBs) and reject blanks early","Log the assembled identifier before calling the library","Validate identifiers at config-load time, not deep in the pipeline"],"tags":["input-validation","argument-parsing"],"backgroundTag":"invalid-identifier-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}