{"record":{"id":"3d90525b8934f6ce","repo":"jackwener/OpenCLI","slug":"label-auth-failed","errorCode":null,"errorMessage":"${label} auth failed.","messagePattern":"(.+?) auth failed\\.","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/salesnav-message.js","lineNumber":165,"sourceCode":"      return ['ok', res.status, json, text];\n    } catch (e) {\n      return ['error', 0, null, '', 'fetch failed: ' + ((e && e.message) || String(e))];\n    }\n  })()`;\n}\n\nfunction requireFetchResult(result, label, { requireJson = true } = {}) {\n  if (Array.isArray(result)) {\n    const [kind, status, json, text, error] = result;\n    result = {\n      authRequired: kind === 'auth',\n      error: kind === 'error' ? error || `HTTP ${status}` : '',\n      status,\n      json,\n      text,\n    };\n  }\n  if (result?.authRequired) throw new AuthRequiredError(LINKEDIN_DOMAIN, `${label} auth failed.`);\n  if (result?.error) throw new CommandExecutionError(`${label} failed`, result.error);\n  if (!result || typeof result !== 'object' || Array.isArray(result)) {\n    throw new CommandExecutionError(`${label} returned malformed response`);\n  }\n  if (requireJson && (!result.json || typeof result.json !== 'object' || Array.isArray(result.json))) {\n    throw new CommandExecutionError(`${label} returned malformed response`, 'missing_json');\n  }\n  return result;\n}\n\nfunction salesPageShowsSentMessage(text, recipientName) {\n  const normalizedText = normalizeWhitespace(text);\n  const firstName = normalizeWhitespace(recipientName).split(' ')[0];\n  return normalizedText.includes('You sent a Sales Navigator message')\n    && (!firstName || normalizedText.includes(firstName));\n}\n\nasync function getCsrf(page) {","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/salesnav-message.js#L147-L183","documentation":"requireFetchResult normalizes every Sales Navigator fetch response and throws AuthRequiredError when the response body flags authRequired:true. LinkedIn returned a page/JSON indicating the session is no longer authenticated, so the CLI aborts instead of proceeding with unauthenticated API calls. The message identifies which step ('profile', 'credits', 'send', 'credits-after') hit the auth wall via the ${label} placeholder.","triggerScenarios":"Any of the four fetches (profile lookup, credits query, send-message createMessage, post-send credits re-query) returns JSON with authRequired=true — typically because JSESSIONID expired mid-run, the session was logged out elsewhere, or LinkedIn redirected an API call to the login page.","commonSituations":"Long-running automations outliving cookie lifetime; running from a server/IP LinkedIn treats as suspicious; sharing one account between browser and automation causing session invalidation; Sales Navigator subscription lapsing.","solutions":["Re-authenticate the browser session (log into linkedin.com in the automation's browser profile) and re-run the command","Persist and reuse a fresh cookie state so JSESSIONID stays valid between runs","Check the LinkedIn/Sales Nav account is still active and subscribed","Reduce automation pace / avoid concurrent sessions that invalidate each other"],"exampleFix":"// before: single long-lived session reused for hours\n// after: re-login before batch runs\nconst page = await browser.newPage();\nawait signIn(page); // ensures fresh JSESSIONID\nconst result = await sendInMail(page, args);","handlingStrategy":"try-catch","validationCode":"// before running: confirm session cookies exist\nconst cookies = await page.getCookies({ url: 'https://www.linkedin.com' });\nif (!cookies.some((c) => c.name === 'JSESSIONID')) throw new Error('Log in to LinkedIn first');","typeGuard":"function hasSession(cookies) {\n  return Array.isArray(cookies) && cookies.some((c) => c.name === 'JSESSIONID' && c.value);\n}","tryCatchPattern":"try {\n  await cli.run('linkedin', 'salesnav-message', page, args);\n} catch (err) {\n  if (/auth failed/i.test(err.message)) {\n    await reauthenticate(page); // fresh login, then retry once\n  } else throw err;\n}","preventionTips":["Restore persisted cookies/storageState at the start of each run","Log in again when JSESSIONID is near expiry","Avoid running duplicate sessions that invalidate each other","Keep the Sales Nav subscription active"],"tags":["auth","linkedin","session-expired","sales-navigator"],"backgroundTag":"auth-session-expired","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}