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
- Update the library so canonicalizeLinkedInInviteUrl recognizes the new LinkedIn invitation URL format
- Log inviteHref to inspect the actual href and confirm which pattern the canonicalizer rejects
- Re-run the command — transient DOM states can yield a wrong href
- 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
- Keep the library updated for new LinkedIn invite URL shapes
- Log inviteHref when this error occurs to diagnose the pattern
- Retry once after a page reload — transient DOM states cause bad hrefs
- Report persistent failures with the raw href to library maintainers
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
- LinkedIn connect blocked: ${safety.blockReason}
- LinkedIn connect blocked: ${opened?.reason || 'connect_contr
- LinkedIn connect blocked: ${result?.reason || 'send_failed'}
- job-url must be a https://www.linkedin.com/jobs/view/<id> UR
- Sales Navigator lead URL must contain resolved profileId, au
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0702256c5fd9b971.
Report an issue: GitHub.