{"record":{"id":"bd852b69afdd1902","repo":"jackwener/OpenCLI","slug":"linkedin-connect-blocked-result-reason-sen","errorCode":null,"errorMessage":"LinkedIn connect blocked: ${result?.reason || 'send_failed'}","messagePattern":"LinkedIn connect blocked: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/connect.js","lineNumber":478,"sourceCode":"            // 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        }\n        // A button-based Connect that fired the invite without a confirmation dialog leaves\n        // no dialog to drive; treat it as sent and let the sent-invitations probe verify.\n        if (!result?.ok && result?.reason === 'invite_dialog_not_found' && !inviteHref) {\n            result = { ok: true, status: 'sent', reason: 'invitation_sent_no_dialog' };\n        }\n        if (!result?.ok) throw new CommandExecutionError(`LinkedIn connect blocked: ${result?.reason || 'send_failed'}`);\n        // LinkedIn can take a few seconds after the Send click to materialize the\n        // new invite in /mynetwork/invitation-manager/sent/. Wait before the\n        // first check, then retry page loads for propagation lag.\n        await page.wait(8);\n        let sentProbe = null;\n        for (let attempt = 0; attempt < 3; attempt += 1) {\n            await page.goto('https://www.linkedin.com/mynetwork/invitation-manager/sent/');\n            await page.wait(attempt === 0 ? 6 : 4);\n            sentProbe = unwrapEvaluateResult(await page.evaluate(buildSentInvitationsProbeScript(expectedName, profileUrl)));\n            if (sentProbe?.found || sentProbe?.authRequired) break;\n            if (attempt < 2) await page.wait(5);\n        }\n        if (sentProbe?.authRequired) {\n            throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn sent-invitations verification requires an active signed-in LinkedIn browser session.');\n        }\n        const verified = Boolean(sentProbe?.found);\n        return [{\n            status: verified ? 'sent_verified' : 'send_unverified',","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/connect.js#L460-L496","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-run the command — dialog timing issues often resolve on a fresh attempt with longer waits","Check your sent-invitations page manually to see whether the invite actually went out despite the error","Slow down the automation cadence; LinkedIn may be soft-blocking rapid invitations","Update the library if LinkedIn changed the invite dialog structure (selectors in buildInviteScript)"],"exampleFix":"null","handlingStrategy":"retry","validationCode":"// pre-flight rate guard: cap invitations per hour to avoid LinkedIn soft blocks\nconst sentLastHour = getSentInvitationsLastHour();\nif (sentLastHour > MAX_INVITES_PER_HOUR) throw new Error('Invitation rate limit reached; wait before sending more.');","typeGuard":"null","tryCatchPattern":"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; } }","preventionTips":["Throttle invitation volume to avoid LinkedIn soft blocks that reject sends","Verify results against the sent-invitations page rather than trusting the click","Increase dialog waits for slow renders","Update the library when the invite dialog markup changes"],"tags":["linkedin","automation","dom"],"backgroundTag":"ui-element-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}