jackwener/OpenCLI · info · EmptyResultError

No LinkedIn Services page link was found on the profile.

Error message

No LinkedIn Services page link was found on the profile.

What it means

When no --services-url is given, services-read loads the profile and runs buildFindServicesUrlScript to discover the profile's Services page link. If the script finds no services_url, the command throws EmptyResultError: the profile has no Services page (or the link could not be detected).

Source

Thrown at clis/linkedin/services-read.js:183

  browser: true,
  args: [
    { name: 'profile-url', type: 'string', required: false, help: 'LinkedIn /in/<handle>/ profile URL. Defaults to /in/me/.' },
    { name: 'services-url', type: 'string', required: false, help: 'LinkedIn /services/page/<id>/ URL. If omitted, it is discovered from the profile.' },
  ],
  columns: ['service_url', 'page_title', 'overview', 'availability', 'work_locations', 'pricing', 'services_provided', 'services_count', 'media', 'media_count', 'messages', 'reviews_visibility'],
  func: async (page, args) => {
    if (!page) throw new CommandExecutionError('Browser session required for linkedin services-read');
    let servicesUrl = normalizeWhitespace(args['services-url']);
    const shouldReadOwnerEdit = !servicesUrl && !normalizeWhitespace(args['profile-url']);
    if (servicesUrl) {
      servicesUrl = normalizeServicesUrl(servicesUrl);
    } else {
      await page.goto(normalizeProfileUrl(args['profile-url']));
      await page.wait(5);
      await assertLinkedInAuthenticated(page, 'LinkedIn services-read profile');
      const found = unwrapEvaluateResult(await page.evaluate(buildFindServicesUrlScript()));
      servicesUrl = normalizeWhitespace(found?.services_url);
      if (!servicesUrl) throw new EmptyResultError('linkedin services-read', 'No LinkedIn Services page link was found on the profile.');
      servicesUrl = normalizeServicesUrl(servicesUrl);
    }

    await page.goto(servicesUrl);
    await page.wait(5);
    await assertLinkedInAuthenticated(page, 'LinkedIn services-read');
    const services = unwrapEvaluateResult(await page.evaluate(buildServicesPageScript()));

    const edit = shouldReadOwnerEdit ? await readOwnerOnlyServicesEdit(page, servicesUrl) : {};

    let media = {};
    if (shouldReadOwnerEdit) {
      const mediaUrl = new URL(servicesUrl);
      mediaUrl.pathname = mediaUrl.pathname.replace(/\/?$/, '/media/');
      await page.goto(mediaUrl.toString());
      await page.wait(4);
      await assertLinkedInAuthenticated(page, 'LinkedIn services-read media');
      media = unwrapEvaluateResult(await page.evaluate(buildMediaPageScript()));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Confirm the profile actually shows a Services page (open it in a browser); if not, this is expected — skip the profile.
  2. If Services exists but was not found, update buildFindServicesUrlScript selectors/text matching to current markup.
  3. If you already know the Services URL, pass it directly via --services-url to skip discovery.

Example fix

// before
await runCommand('linkedin services-read', ['--profile-url', profileUrl]);
// after (skip discovery when URL is known)
await runCommand('linkedin services-read', ['--services-url', 'https://www.linkedin.com/services/page/1234abc/']);
Defensive patterns

Strategy: fallback

Validate before calling

// pre-check: only run for profiles known to have Services enabled
if (!profile.hasServicesFeature) return null;

Try / catch

try {
  return await runCommand('linkedin services-read', ['--profile-url', url]);
} catch (e) {
  if (e.name === 'EmptyResultError') return null; // profile has no Services page
  throw e;
}

Prevention

When it happens

Trigger: Running services-read with only --profile-url (or defaulting to /in/me/) on a profile where the Services feature is disabled, or where LinkedIn markup changes prevent the discovery script from finding the link.

Common situations: Profiles without Services enabled (most members); scraping a profile in a locale/language where the Services button text differs and the finder relies on text; creator-mode Services toggle turned off.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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