jackwener/OpenCLI · error · CommandExecutionError

LinkedIn connect blocked: ${result?.reason || 'send_failed'}

Error message

LinkedIn connect blocked: ${result?.reason || 'send_failed'}

What it means

After opening the invite dialog, the command runs buildInviteScript to fill the note and click Send. If the script does not report ok — and the special no-dialog case (button-based connect that fired without confirmation) does not apply — the command throws CommandExecutionError with the script's failure reason, defaulting to send_failed.

Source

Thrown at clis/linkedin/connect.js:478

            // Button-based Connect: no /preload/custom-invite/ anchor exists, so open the
            // invite dialog in-page by clicking the Connect control (directly or via More).
            const opened = unwrapEvaluateResult(await page.evaluate(buildOpenConnectDialogScript(expectedName)));
            if (!opened?.ok) {
                throw new CommandExecutionError(`LinkedIn connect blocked: ${opened?.reason || 'connect_control_not_found'}`);
            }
            await page.wait(3);
        }
        let result = unwrapEvaluateResult(await page.evaluate(buildInviteScript(note)));
        if (result?.reason === 'invite_dialog_not_found') {
            await page.wait(5);
            result = unwrapEvaluateResult(await page.evaluate(buildInviteScript(note)));
        }
        // A button-based Connect that fired the invite without a confirmation dialog leaves
        // no dialog to drive; treat it as sent and let the sent-invitations probe verify.
        if (!result?.ok && result?.reason === 'invite_dialog_not_found' && !inviteHref) {
            result = { ok: true, status: 'sent', reason: 'invitation_sent_no_dialog' };
        }
        if (!result?.ok) throw new CommandExecutionError(`LinkedIn connect blocked: ${result?.reason || 'send_failed'}`);
        // LinkedIn can take a few seconds after the Send click to materialize the
        // new invite in /mynetwork/invitation-manager/sent/. Wait before the
        // first check, then retry page loads for propagation lag.
        await page.wait(8);
        let sentProbe = null;
        for (let attempt = 0; attempt < 3; attempt += 1) {
            await page.goto('https://www.linkedin.com/mynetwork/invitation-manager/sent/');
            await page.wait(attempt === 0 ? 6 : 4);
            sentProbe = unwrapEvaluateResult(await page.evaluate(buildSentInvitationsProbeScript(expectedName, profileUrl)));
            if (sentProbe?.found || sentProbe?.authRequired) break;
            if (attempt < 2) await page.wait(5);
        }
        if (sentProbe?.authRequired) {
            throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn sent-invitations verification requires an active signed-in LinkedIn browser session.');
        }
        const verified = Boolean(sentProbe?.found);
        return [{
            status: verified ? 'sent_verified' : 'send_unverified',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command — dialog timing issues often resolve on a fresh attempt with longer waits
  2. Check your sent-invitations page manually to see whether the invite actually went out despite the error
  3. Slow down the automation cadence; LinkedIn may be soft-blocking rapid invitations
  4. Update the library if LinkedIn changed the invite dialog structure (selectors in buildInviteScript)

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight rate guard: cap invitations per hour to avoid LinkedIn soft blocks
const sentLastHour = getSentInvitationsLastHour();
if (sentLastHour > MAX_INVITES_PER_HOUR) throw new Error('Invitation rate limit reached; wait before sending more.');

Type guard

null

Try / catch

try { await runConnect(args); } catch (e) { if (String(e.message).startsWith('LinkedIn connect blocked:')) { await page.wait(30); /* backoff then verify sent-invitations manually */ } else { throw e; } }

Prevention

When it happens

Trigger: The invite dialog was not found at the expected step (reason invite_dialog_not_found even after retries), the Send button could not be clicked, LinkedIn showed an error/toaster, or the note field was rejected.

Common situations: LinkedIn dialog markup drift; rate limiting or a soft block silently rejecting the invitation; the dialog rendered in an unexpected variant (mobile layout, modal without note); slow rendering causing premature probing.

Related errors


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