jackwener/OpenCLI · error · ArgumentError

${label} must be an exact https://www.linkedin.com/messaging

Error message

${label} must be an exact https://www.linkedin.com/messaging/thread/<id>/ URL

What it means

requireLinkedInThreadUrl canonicalizes the input via canonicalizeLinkedInThreadUrl and throws ArgumentError when the value does not canonicalize to an exact https://www.linkedin.com/messaging/thread/<id>/ URL. The URL must match LinkedIn's messaging thread pattern precisely — other paths, hosts, or extra fragments fail.

Source

Thrown at clis/linkedin/thread-snapshot.js:20

import { ArgumentError, AuthRequiredError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';
import {
  canonicalizeLinkedInThreadUrl,
  normalizeWhitespace,
  requireLinkedInCookie,
  unwrapEvaluateResult,
} from './shared.js';

const LINKEDIN_DOMAIN = 'www.linkedin.com';

function requireStringArg(args, key, label = key) {
  const value = normalizeWhitespace(args[key]);
  if (!value) throw new ArgumentError(`${label} is required`);
  return value;
}

function requireLinkedInThreadUrl(value, label) {
  const url = canonicalizeLinkedInThreadUrl(value);
  if (!url) throw new ArgumentError(`${label} must be an exact https://www.linkedin.com/messaging/thread/<id>/ URL`);
  return url;
}

function parseMaxScrolls(value) {
  if (value === undefined || value === null || value === '') return 30;
  const scrolls = Number(value);
  if (!Number.isInteger(scrolls) || scrolls < 0 || scrolls > 80) {
    throw new ArgumentError('--max-scrolls must be an integer between 0 and 80');
  }
  return scrolls;
}

function buildThreadApiDiscoveryScript(maxScrolls) {
  return String.raw`(async () => {
    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    const pageText = document.body ? (document.body.innerText || '') : '';
    const authRequired = /\b(sign in|log in|join linkedin)\b/i.test(pageText)
      || /linkedin\.com\/(login|checkpoint|authwall|uas)/i.test(location.href)

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Copy the full URL while viewing the thread: https://www.linkedin.com/messaging/thread/<threadId>/.
  2. Remove query strings/extra fragments; ensure https and the www.linkedin.com host.
  3. Fix truncation/encoding of the thread ID (long alphanumeric string).
  4. Verify the shape before calling with a regex like /^https:\/\/www\.linkedin\.com\/messaging\/thread\/[A-Za-z0-9-_]+\/$/.

Example fix

// before
--thread-url "https://www.linkedin.com/feed/update/urn:li:activity:123/"
// after
--thread-url "https://www.linkedin.com/messaging/thread/AbCdEf123_/"
Defensive patterns

Strategy: validation

Validate before calling

const THREAD_URL_RE = /^https:\/\/www\.linkedin\.com\/messaging\/thread\/[A-Za-z0-9_-]+\/$/;
function isValidThreadUrl(u) {
  return typeof u === 'string' && THREAD_URL_RE.test(u.trim());
}
if (!isValidThreadUrl(threadUrl)) throw new Error('Pass an exact https://www.linkedin.com/messaging/thread/<id>/ URL');

Type guard

function isLinkedInThreadUrl(v) {
  if (typeof v !== 'string') return false;
  try {
    const u = new URL(v);
    return u.protocol === 'https:' && u.hostname === 'www.linkedin.com' &&
      /^\/messaging\/thread\/[A-Za-z0-9_-]+\/$/.test(u.pathname);
  } catch { return false; }
}

Try / catch

try {
  await threadSnapshot({ 'thread-url': threadUrl });
} catch (e) {
  if (e instanceof ArgumentError && e.message.includes('messaging/thread')) {
    console.error('Not a valid thread URL. Copy it from an open LinkedIn message thread.');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a profile or feed URL instead of a messaging thread URL, a thread URL without the ID, a URL with extra path segments or query strings that fail canonicalization, a non-www host, or http instead of https.

Common situations: Copying the wrong URL from the browser (post/feed instead of thread), URL-encoding mangling the ID, using a mobile or short-link form, truncated thread ID from logs.

Related errors


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