{"record":{"id":"0702256c5fd9b971","repo":"jackwener/OpenCLI","slug":"linkedin-connect-blocked-invalid-connect-link","errorCode":null,"errorMessage":"LinkedIn connect blocked: invalid_connect_link","messagePattern":"LinkedIn connect blocked: invalid_connect_link","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/connect.js","lineNumber":454,"sourceCode":"        if (!safety.ok && safety.safety === 'routine_non_connectable') {\n            return [{ status: 'not_connectable', recipient: safety.actualValue, reason: safety.blockReason, profile_url: safety.observedUrl, note_chars: note.length, connectable: false }];\n        }\n        if (!safety.ok) {\n            throw new CommandExecutionError(\n                `LinkedIn connect blocked: ${safety.blockReason}`,\n                `Expected ${safety.expectedValue}; actual ${safety.actualValue || 'not_visible'} at ${safety.observedUrl || 'url_not_available'}\\nButtons: ${(probe?.buttonLabels || []).join(' | ')}`,\n            );\n        }\n        if (!args.send) {\n            return [{ status: 'connectable_dry_run', recipient: safety.actualValue, reason: safety.blockReason, profile_url: safety.observedUrl, note_chars: note.length, connectable: true }];\n        }\n        const inviteHref = probe?.connectHref || '';\n        if (inviteHref) {\n            // Anchor-based Connect: navigate straight to the invitation route, where the\n            // \"Add a note?\" dialog renders already open.\n            const inviteUrl = canonicalizeLinkedInInviteUrl(inviteHref);\n            if (!inviteUrl) {\n                throw new CommandExecutionError('LinkedIn connect blocked: invalid_connect_link');\n            }\n            await page.goto(inviteUrl);\n            await page.wait(6);\n        }\n        else {\n            // Button-based Connect: no /preload/custom-invite/ anchor exists, so open the\n            // invite dialog in-page by clicking the Connect control (directly or via More).\n            const opened = unwrapEvaluateResult(await page.evaluate(buildOpenConnectDialogScript(expectedName)));\n            if (!opened?.ok) {\n                throw new CommandExecutionError(`LinkedIn connect blocked: ${opened?.reason || 'connect_control_not_found'}`);\n            }\n            await page.wait(3);\n        }\n        let result = unwrapEvaluateResult(await page.evaluate(buildInviteScript(note)));\n        if (result?.reason === 'invite_dialog_not_found') {\n            await page.wait(5);\n            result = unwrapEvaluateResult(await page.evaluate(buildInviteScript(note)));\n        }","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/connect.js#L436-L472","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"null","handlingStrategy":"retry","validationCode":"// pre-check the captured anchor is a LinkedIn invite route before running the command\nif (connectHref && !/^https?:\\/\\/(www\\.)?linkedin\\.com\\//.test(connectHref)) throw new Error('Connect href is not a linkedin.com invitation link: ' + connectHref);","typeGuard":"function isLinkedInInviteHref(v) { return typeof v === 'string' && /^https?:\\/\\/(www\\.)?linkedin\\.com\\//.test(v) && !v.includes(' '); }","tryCatchPattern":"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; } }","preventionTips":["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"],"tags":["linkedin","url","automation"],"backgroundTag":"invalid-url-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}