jackwener/OpenCLI · error · Error

Could not resolve post.id from the component page: ${normali

Error message

Could not resolve post.id from the component page: ${normalized.url}

What it means

Thrown by getPostDetails when it cannot obtain routeData containing post.id, either from the Remix context embedded in the page (window.__remixContext) or from the ?_data= fallback request. Without post.id the tool cannot fetch the component's raw code, so it aborts.

Source

Thrown at clis/uiverse/_shared.js:99

  const normalized = parseComponentInput(input);
  await page.goto(normalized.url);

  const raw = await page.evaluate(`(async () => {
    const key = ${JSON.stringify(ROUTE_DATA_KEY)};
    const loaderData = window.__remixContext?.state?.loaderData || {};
    const routeData = loaderData[key];
    return JSON.stringify({ routeData: routeData || null, keys: Object.keys(loaderData) });
  })()`);

  const parsed = JSON.parse(raw);
  let routeData = parsed?.routeData;
  if (!routeData?.post?.id) {
    const routeUrl = `${normalized.url}?_data=${encodeURIComponent(ROUTE_DATA_KEY)}`;
    routeData = await fetchJsonInBrowser(page, routeUrl);
  }

  if (!routeData?.post?.id) {
    throw new Error(`Could not resolve post.id from the component page: ${normalized.url}`);
  }

  return {
    ...normalized,
    post: routeData.post,
    routeData,
  };
}

export async function getRawCode(page, postId) {
  const codeUrl = `${UIVERSE_BASE_URL}/resource/post/code/${postId}?v=1&_data=${encodeURIComponent(CODE_DATA_KEY)}`;
  const payload = await fetchJsonInBrowser(page, codeUrl);
  if (typeof payload?.html !== 'string' || typeof payload?.css !== 'string') {
    throw new Error(`Unexpected code payload shape: ${codeUrl}`);
  }
  return payload;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Confirm the URL is an individual component page (uiverse.io/<author>/<slug>) that renders a preview
  2. Wait for hydration before evaluating: wait for a known selector or networkidle after page.goto, then retry getPostDetails
  3. Inspect window.__remixContext keys in the live page and update ROUTE_DATA_KEY if the route name changed
  4. Check uiverse.io for API/site changes; update the loader-data extraction logic in clis/uiverse/_shared.js accordingly

Example fix

// before
await page.goto(normalized.url);
const details = await getPostDetails(page, input); // context not hydrated yet
// after
await page.goto(normalized.url, { waitUntil: 'networkidle' });
await page.waitForSelector('[class*="wrapper"], main', { timeout: 15000 });
const details = await getPostDetails(page, input);
Defensive patterns

Strategy: retry

Validate before calling

await page.goto(url, { waitUntil: 'networkidle' });
const hasContext = await page.evaluate(() =>
  Boolean(window.__remixContext?.state?.loaderData?.['routes/$username.$friendlyId']?.post?.id)
);
if (!hasContext) await page.waitForTimeout(2000); // let hydration finish before getPostDetails

Type guard

const hasPostId = (routeData) => typeof routeData?.post?.id === 'string' || typeof routeData?.post?.id === 'number';

Try / catch

try {
  const details = await getPostDetails(page, input);
} catch (e) {
  if (e.message.startsWith('Could not resolve post.id')) {
    await page.reload({ waitUntil: 'networkidle' }); // retry once after full load
    return getPostDetails(page, input);
  }
  throw e;
}

Prevention

When it happens

Trigger: The component page structure changed so __remixContext.state.loaderData no longer carries 'routes/$username.$friendlyId' with post.id; the ?_data= fallback returns data without post.id (route key renamed after a site update); page.goto failed to hydrate the Remix app before evaluate ran; the URL points to a page that is not a component page.

Common situations: Uiverse deploys a framework/router upgrade renaming loader routes; slow page load/hydration so context is missing when evaluated; scraping a profile or element page instead of an individual component page; SSR disabled/changed.

Related errors


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