{"record":{"id":"5af44b21b46ba562","repo":"jackwener/OpenCLI","slug":"linkedin-learning-auth-failed-http-result-statu","errorCode":null,"errorMessage":"LinkedIn Learning auth failed (HTTP ${result.status ?? ''}).","messagePattern":"LinkedIn Learning auth failed \\(HTTP (.+?)\\)\\.","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/linkedin-learning/shared.js","lineNumber":57,"sourceCode":"      return { error: 'fetch failed: ' + ((e && e.message) || String(e)) };\n    }\n  })()`;\n}\n\nexport async function fetchLinkedInLearningApi(page, url) {\n    await page.goto('https://www.linkedin.com/learning/');\n    await page.wait(3);\n\n    const cookies = await page.getCookies({ url: 'https://www.linkedin.com' });\n    const jsession = cookies.find((c) => c.name === 'JSESSIONID')?.value;\n    if (!jsession) {\n        throw new AuthRequiredError(DOMAIN, 'LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn in the browser.');\n    }\n    const csrf = jsession.replace(/^\"|\"$/g, '');\n\n    const result = unwrapEvaluateResult(await page.evaluate(buildFetchScript(url, csrf)));\n    if (result?.authRequired) {\n        throw new AuthRequiredError(DOMAIN, `LinkedIn Learning auth failed (HTTP ${result.status ?? ''}).`);\n    }\n    return result;\n}\n","sourceCodeStart":39,"sourceCodeEnd":61,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin-learning/shared.js#L39-L61","documentation":"An AuthRequiredError thrown when the in-page API fetch returns HTTP 401 or 403 — buildFetchScript maps those statuses to {authRequired:true, status}. Unlike error 2275, a JSESSIONID cookie existed, but the server rejected the request: the session cookie is stale/expired or the derived csrf-token did not match, so LinkedIn's API rejected the authenticated call.","triggerScenarios":"The JSESSIONID is present but expired server-side (soft logout), the csrf header derived from JSESSIONID (quotes stripped) does not match what LinkedIn expects, or the account is restricted/blocked from the learning-api endpoint (403).","commonSituations":"Long-lived automation profiles whose session silently expired, LinkedIn rotating session tokens after a security event, corporate/region restrictions returning 403, or clock/JAR inconsistencies after cookie export.","solutions":["Re-login in the controlled browser to refresh the session, then retry.","If 403 persists, check account standing/region access to LinkedIn Learning in the web UI.","Confirm the csrf-token header equals JSESSIONID with surrounding double quotes stripped.","Clear linkedin.com cookies and sign in fresh (stale-cookie mismatch).","Retry after completing any LinkedIn verification prompt in the browser."],"exampleFix":"// before\nconst csrf = jsession.replace(/^\"|\"$/g, ''); // assumes only quote trimming is needed\n// after\nconst csrf = decodeURIComponent(jsession.replace(/^\"|\"$/g, ''));\nif (result?.authRequired && result.status === 401) throw new AuthRequiredError(DOMAIN, 'Session expired; re-login required.');","handlingStrategy":"retry","validationCode":"// pre-flight: confirm the session is live by hitting a cheap authenticated page\nawait page.goto('https://www.linkedin.com/learning/');\nconst signedOut = await page.evaluate(() => !!document.querySelector('a[href*=\"/login\"]'));\nif (signedOut) throw new Error('LinkedIn session expired; re-login before running API commands');","typeGuard":"function isAuthRejection(r) { return !!r && typeof r === 'object' && r.authRequired === true && typeof r.status === 'number'; }","tryCatchPattern":"try {\n  const rows = await search(page, { keywords });\n} catch (e) {\n  if (/auth failed \\(HTTP 40[13]\\)/.test(e.message)) {\n    await relogin(page);      // refresh JSESSIONID, re-derive csrf\n    return search(page, { keywords }); // retry once with fresh session\n  }\n  throw e;\n}","preventionTips":["Re-login periodically; JSESSIONID expires server-side even if the cookie exists","Strip surrounding quotes from JSESSIONID exactly as the CLI does when comparing csrf values","On 401 always refresh the session before retrying — the old cookie will keep failing","Investigate 403 for account/region restrictions on LinkedIn Learning","Watch for LinkedIn security challenges that silently downgrade sessions"],"tags":["auth","csrf","http-403","http-401","linkedin"],"backgroundTag":"csrf-token-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}