{"record":{"id":"08b5cfa9baf07516","repo":"jackwener/OpenCLI","slug":"linkedin-warning-restriction-state-visible-on-sent","errorCode":null,"errorMessage":"LinkedIn warning/restriction state visible on sent invitations page.","messagePattern":"LinkedIn warning/restriction state visible on sent invitations page\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/sent-invitations.js","lineNumber":99,"sourceCode":"  site: 'linkedin',\n  name: 'sent-invitations',\n  access: 'read',\n  description: 'List pending LinkedIn sent invitations for CRM reconciliation',\n  domain: LINKEDIN_DOMAIN,\n  strategy: Strategy.UI,\n  browser: true,\n  args: [],\n  columns: ['rank', 'name', 'profile_url', 'invited_date_text'],\n  func: async (page) => {\n    if (!page) throw new CommandExecutionError('Browser session required for linkedin sent-invitations');\n    await page.goto(SENT_URL);\n    await page.wait(12);\n    let result = unwrapEvaluateResult(await page.evaluate(buildSentInvitationsScript()));\n    if (result?.authRequired) {\n      throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn sent invitations requires an active signed-in browser session.');\n    }\n    if (result?.warning) {\n      throw new CommandExecutionError('LinkedIn warning/restriction state visible on sent invitations page.');\n    }\n    if (!result || typeof result !== 'object' || Array.isArray(result) || !Array.isArray(result.rows)) {\n      throw new CommandExecutionError('LinkedIn sent invitations returned a malformed extraction payload.');\n    }\n    if (result.malformedCount > 0) {\n      throw new CommandExecutionError('LinkedIn sent invitations contained a malformed invitation card.');\n    }\n    const rows = result.rows;\n    if (rows.length === 0) {\n      if (result.explicitEmpty) {\n        throw new EmptyResultError('linkedin sent-invitations', 'No pending sent invitations were found.');\n      }\n      throw new CommandExecutionError('LinkedIn sent invitation cards were not found; the page structure may have changed.');\n    }\n    return rows.map((row, index) => ({\n      rank: index + 1,\n      name: row.name || '',\n      profile_url: row.profile_url || '',","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/sent-invitations.js#L81-L117","documentation":"The extraction script scans the sent-invitations page for LinkedIn restriction signals: captcha, 'verification required', 'unusual activity', 'account restricted', 'security check', or 'checkpoint' text. If found, the command refuses to scrape (both to protect the account and to avoid garbage data) and throws this CommandExecutionError.","triggerScenarios":"Running `opencli linkedin sent-invitations` while the rendered page contains restriction text, e.g. the account is temporarily restricted, LinkedIn interposes a captcha/security-check challenge, or an 'unusual activity' banner is shown.","commonSituations":"Aggressive scraping volume tripping LinkedIn's anti-automation; account already flagged/restricted by LinkedIn; running from a flagged IP (VPN/datacenter); LinkedIn A/B-serving a security challenge to the session.","solutions":["Stop automated calls immediately and open the page manually in the browser to complete any captcha/security challenge LinkedIn is presenting.","Check your account status at linkedin.com — if restricted, follow LinkedIn's recovery flow before resuming.","Reduce scraping frequency, add delays between commands, and run from a residential IP rather than a datacenter/VPN.","Once the page renders normally (no warning banners) in the browser, re-run the command."],"exampleFix":"// before (retrying through a captcha makes it worse)\nfor (let i = 0; i < 5; i++) { await run(['linkedin', 'sent-invitations']); await sleep(5000); }\n// after — pause automation until the challenge is cleared manually\ntry { await run(['linkedin', 'sent-invitations']); }\ncatch (e) {\n  if (/warning\\/restriction/.test(e.message)) {\n    console.error('Complete the LinkedIn challenge in the browser, then retry.');\n    process.exit(1);\n  }\n}","handlingStrategy":"try-catch","validationCode":"// Inspect the page before running: abort if LinkedIn is showing restriction banners\nconst result = await page.evaluate(() => document.body?.innerText?.slice(0, 4000) || '');\nconst restricted = /captcha|verification required|unusual activity|account restricted|temporarily restricted|security check|checkpoint/i.test(result);\nif (restricted) {\n  console.error('LinkedIn is showing a restriction/challenge page — resolve it manually before automating.');\n  process.exit(2);\n}","typeGuard":"const showsRestriction = (pageText) =>\n  /captcha|verification required|unusual activity|account restricted|temporarily restricted|security check|checkpoint/i.test(String(pageText || ''));","tryCatchPattern":"try {\n  const rows = await run(['linkedin', 'sent-invitations']);\n} catch (e) {\n  if (/warning\\/restriction state/.test(e.message)) {\n    console.error('Pause all LinkedIn automation; complete the challenge/restriction manually, then resume slowly.');\n    process.exit(2); // do NOT auto-retry through a restriction\n  }\n  throw e;\n}","preventionTips":["Never auto-retry when LinkedIn shows a restriction — back off completely until cleared manually.","Throttle command frequency and add randomized delays between runs.","Run from residential IPs; avoid VPNs and datacenter ranges LinkedIn flags.","Monitor account standing and stop automation at the first 'unusual activity' signal."],"tags":["linkedin","anti-bot","account-restricted","captcha","scraping"],"backgroundTag":"account-restricted-by-site","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}