jackwener/OpenCLI · error · ArgumentError

job-url must be a https://www.linkedin.com/jobs/view/<id> UR

Error message

job-url must be a https://www.linkedin.com/jobs/view/<id> URL

What it means

normalizeJobUrl first runs assertSafeLinkedinUrl (rejecting non-LinkedIn/unsafe URLs) and then requires the path to match /jobs/view/<id> or a currentJobId=<id> query param. If neither pattern matches, an ArgumentError is thrown because no job id can be extracted to build the detail query URL.

Source

Thrown at clis/linkedin/job-detail.js:15

import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';
import {
  assertLinkedInAuthenticated,
  assertSafeLinkedinUrl,
  normalizeHttpUrl,
  normalizeWhitespace,
  unwrapEvaluateResult,
} from './shared.js';

function normalizeJobUrl(value) {
  const url = assertSafeLinkedinUrl(value, 'job-url');
  const parsed = new URL(url);
  const match = parsed.pathname.match(/^\/jobs\/view\/(\d+)/) || parsed.search.match(/[?&]currentJobId=(\d+)/);
  if (!match) throw new ArgumentError('job-url must be a https://www.linkedin.com/jobs/view/<id> URL');
  return `https://www.linkedin.com/jobs/search/?currentJobId=${match[1]}`;
}

function decodeLinkedinRedirect(url) {
  if (!url) return '';
  try {
    const parsed = new URL(url);
    if (parsed.pathname === '/redir/redirect/') return normalizeHttpUrl(parsed.searchParams.get('url') || '');
  } catch {}
  return normalizeHttpUrl(url);
}

function buildExtractionScript() {
  return String.raw`(() => {
    const clean = (s) => String(s || '').replace(/[\u00a0\u202f]+/g, ' ').replace(/\s+/g, ' ').trim();
    const readRenderedDescription = () => {
      const expanders = Array.from(document.querySelectorAll('button, a'))
        .filter((el) => /\b(show more|see more|more)\b/i.test(clean(el.innerText || el.textContent || el.getAttribute('aria-label') || '')));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass the full job view URL containing a numeric id: https://www.linkedin.com/jobs/view/<numericId>/.
  2. If you have a search URL, extract currentJobId from it or open the job and copy the canonical /jobs/view/<id> URL.
  3. Resolve shortened (lnkd.in) or redirect URLs to their final linkedin.com/jobs/view/<id> form before calling.
  4. Validate the id client-side: /linkedin\.com\/(jobs\/view\/(\d+)|.*currentJobId=(\d+))/ before invoking.

Example fix

// before
jobDetail('https://www.linkedin.com/jobs/search/?keywords=engineer'); // ArgumentError

// after
jobDetail('https://www.linkedin.com/jobs/view/3987654321/');
Defensive patterns

Strategy: validation

Validate before calling

const JOB_URL_RE = /^https:\/\/www\.linkedin\.com\/jobs\/view\/(\d+)/;
const jobIdFromUrl = (u) => {
  const m = String(u).match(JOB_URL_RE) || String(u).match(/[?&]currentJobId=(\d+)/);
  if (!m) throw new TypeError('Expected a linkedin.com/jobs/view/<id> URL');
  return m[1];
};

Type guard

const isLinkedinJobUrl = (u) =>
  typeof u === 'string' &&
  (/^https:\/\/www\.linkedin\.com\/jobs\/view\/\d+/.test(u) || /[?&]currentJobId=\d+/.test(u));

Try / catch

try {
  await linkedinJobDetail(jobUrl);
} catch (e) {
  if (e instanceof ArgumentError && /job-url/.test(e.message)) {
    const id = await resolveJobIdFromSearchOrRedirect(jobUrl);
    return linkedinJobDetail(`https://www.linkedin.com/jobs/view/${id}/`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the job-detail command with a job URL like https://www.linkedin.com/jobs/view/some-slug without a numeric id, a jobs collection URL (/jobs/search/...), a truncated URL, or a non-LinkedIn URL that slipped past the safety check but lacks the job-id pattern.

Common situations: Copying a job-search results URL instead of a specific job view URL, URLs where the id lives only in a tracking redirect, sharing mobile app links (linkd.in shorteners) that were never resolved, or malformed saved links from a database.

Related errors


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