jackwener/OpenCLI · error · Error

Invalid component identifier

Error message

Invalid component identifier: ${raw}. Expected author/slug.

What it means

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.

Solutions

  1. Ensure both author and slug are non-empty, e.g. 'pravsingh/sky-button'
  2. Check upstream variables feeding the identifier (log them before calling the CLI)
  3. Copy the identifier directly from the component page URL instead of constructing it
  4. Sanitize source data: replace blank slugs with the real component slug

Example fix

// before
await getPostDetails(page, `${author}/`); // slug empty -> 'Invalid component identifier'
// after
if (!author || !slug) throw new Error('author and slug are both required');
await getPostDetails(page, `${author}/${slug}`);
Defensive patterns

Strategy: validation

Validate before calling

function assertCompleteIdentifier([username, slug]) {
  if (!username?.trim() || !slug?.trim()) throw new Error('both author and slug are required');
}
const segs = input.split('/').filter(Boolean);
assertCompleteIdentifier(segs);

Type guard

const isCompletePair = (v) =>
  typeof v === 'string' && v.split('/').filter(s => s.trim()).length === 2;

Try / catch

try {
  const details = await getPostDetails(page, input);
} catch (e) {
  if (e.message.startsWith('Invalid component identifier')) {
    console.error(`Malformed identifier '${input}' — check for empty author or slug.`);
    process.exit(2);
  }
  throw e;
}

Prevention

When it happens

Trigger: 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/'.

Common situations: 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.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/b155995b6d9b6d1c. Report an issue: GitHub.

Appendix: source

Thrown at clis/uiverse/_shared.js:38

  let pathname = raw;
  if (/^https?:\/\//i.test(raw)) {
    const url = new URL(raw);
    if (url.hostname !== 'uiverse.io' && url.hostname !== 'www.uiverse.io') {
      throw new Error(`Unsupported non-Uiverse URL: ${raw}`);
    }
    pathname = url.pathname;
  }

  const cleaned = trimPathSegment(pathname);
  const segments = cleaned.split('/').filter(Boolean);
  if (segments.length !== 2) {
    throw new Error(`Could not parse author/slug from input: ${raw}`);
  }

  const [username, slug] = segments;
  if (!username || !slug) {
    throw new Error(`Invalid component identifier: ${raw}. Expected author/slug.`);
  }

  return {
    raw,
    username,
    slug,
    url: `${UIVERSE_BASE_URL}/${username}/${slug}`,
  };
}

async function fetchJsonInBrowser(page, url) {
  const raw = await page.evaluate(`(async () => {
    const url = ${JSON.stringify(url)};
    const response = await fetch(url, {
      credentials: 'include',
      headers: {
        accept: 'application/json, text/plain, */*',
      },

View on GitHub (pinned to 49907e53dc)