jackwener/OpenCLI · error · CommandExecutionError

LinkedIn connect blocked: invalid_connect_link

Error message

LinkedIn connect blocked: invalid_connect_link

What it means

Anchor-based Connect: the probe found a connectHref anchor and the command navigates to its canonicalized invitation route, where the 'Add a note?' dialog renders open. If canonicalizeLinkedInInviteUrl cannot produce a valid LinkedIn invite URL from that href (off-domain, malformed, or unexpected route), the command throws to avoid clicking into an untrusted or broken link.

Source

Thrown at clis/linkedin/connect.js:454

        if (!safety.ok && safety.safety === 'routine_non_connectable') {
            return [{ status: 'not_connectable', recipient: safety.actualValue, reason: safety.blockReason, profile_url: safety.observedUrl, note_chars: note.length, connectable: false }];
        }
        if (!safety.ok) {
            throw new CommandExecutionError(
                `LinkedIn connect blocked: ${safety.blockReason}`,
                `Expected ${safety.expectedValue}; actual ${safety.actualValue || 'not_visible'} at ${safety.observedUrl || 'url_not_available'}\nButtons: ${(probe?.buttonLabels || []).join(' | ')}`,
            );
        }
        if (!args.send) {
            return [{ status: 'connectable_dry_run', recipient: safety.actualValue, reason: safety.blockReason, profile_url: safety.observedUrl, note_chars: note.length, connectable: true }];
        }
        const inviteHref = probe?.connectHref || '';
        if (inviteHref) {
            // Anchor-based Connect: navigate straight to the invitation route, where the
            // "Add a note?" dialog renders already open.
            const inviteUrl = canonicalizeLinkedInInviteUrl(inviteHref);
            if (!inviteUrl) {
                throw new CommandExecutionError('LinkedIn connect blocked: invalid_connect_link');
            }
            await page.goto(inviteUrl);
            await page.wait(6);
        }
        else {
            // 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)));
        }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the library so canonicalizeLinkedInInviteUrl recognizes the new LinkedIn invitation URL format
  2. Log inviteHref to inspect the actual href and confirm which pattern the canonicalizer rejects
  3. Re-run the command — transient DOM states can yield a wrong href
  4. Fall back to the button-based Connect flow (clear the anchor) if the library exposes that path

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

// pre-check the captured anchor is a LinkedIn invite route before running the command
if (connectHref && !/^https?:\/\/(www\.)?linkedin\.com\//.test(connectHref)) throw new Error('Connect href is not a linkedin.com invitation link: ' + connectHref);

Type guard

function isLinkedInInviteHref(v) { return typeof v === 'string' && /^https?:\/\/(www\.)?linkedin\.com\//.test(v) && !v.includes(' '); }

Try / catch

try { await runConnect(args); } catch (e) { if (String(e.message).includes('invalid_connect_link')) { /* refresh page / retry once, then report */ await runConnect(args); } else { throw e; } }

Prevention

When it happens

Trigger: The scraped Connect anchor href is malformed, relative in an unexpected way, points outside linkedin.com, or LinkedIn changed the invitation route so the canonicalizer rejects it.

Common situations: LinkedIn A/B testing new invite URLs; profile pages containing a Connect link with tracking params or a novel path; DOM drift causing the wrong anchor's href to be captured.

Related errors


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