{"record":{"id":"f629fa01756c10cf","repo":"jackwener/OpenCLI","slug":"jd-pin-cookie-empty-after-decode-probe-detail","errorCode":null,"errorMessage":"JD pin cookie empty after decode (probe.detail)","messagePattern":"JD pin cookie empty after decode \\(probe\\.detail\\)","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/jd/auth.js","lineNumber":28,"sourceCode":"async function verifyJdIdentity(page) {\n  if (!await hasJdSessionCookie(page)) {\n    throw new AuthRequiredError('jd.com', 'JD pin / thor cookie missing');\n  }\n  await page.goto('https://home.jd.com/');\n  await page.wait(3);\n  const probe = await page.evaluate(`\n    (() => {\n      const pinCookie = (document.cookie.split('; ').find(c => c.startsWith('pin=')) || '').split('=')[1] || '';\n      const decoded = pinCookie ? decodeURIComponent(pinCookie) : '';\n      if (!decoded) {\n        return { kind: 'auth', detail: 'JD pin cookie empty after decode' };\n      }\n      const nickEl = document.querySelector('.user-info, #aliveUserName, .name, .user-name');\n      const nickname = (nickEl && nickEl.textContent && nickEl.textContent.trim()) || '';\n      return { ok: true, pin: decoded, nickname };\n    })()\n  `);\n  if (probe?.kind === 'auth') throw new AuthRequiredError('jd.com', probe.detail);\n  if (!probe?.ok) throw new CommandExecutionError(`Unexpected JD probe: ${JSON.stringify(probe)}`);\n  return { pin: probe.pin, nickname: probe.nickname };\n}\n\nregisterSiteAuthCommands({\n  site: 'jd',\n  domain: 'jd.com',\n  loginUrl: 'https://passport.jd.com/new/login.aspx',\n  columns: ['pin', 'nickname'],\n  quickCheck: hasJdSessionCookie,\n  verify: verifyJdIdentity,\n  poll: async (page) => {\n    if (!await hasJdSessionCookie(page)) {\n      throw new AuthRequiredError('jd.com', 'Waiting for JD pin / thor cookie');\n    }\n    return verifyJdIdentity(page);\n  },\n});","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/jd/auth.js#L10-L46","documentation":"verifyJdIdentity throws AuthRequiredError('jd.com', probe.detail) when the in-page probe reports kind='auth' with detail 'JD pin cookie empty after decode (probe.detail)' — the 'pin' cookie exists but its decoded value is empty/invalid, so the session is unusable even though a cookie is present.","triggerScenarios":"The JD 'pin' cookie is present but empty after decodeURIComponent, typically a stale or cleared-value cookie left behind after logout or partial session expiry; detected inside the page.evaluate probe on home.jd.com.","commonSituations":"Half-expired JD session: cookie exists but server invalidated it; cookie set with empty value by JD on logout; corrupted cookie from an old login.","solutions":["Delete the stale JD cookies (pin/thor) in the browser profile and log in again at https://www.jd.com","Run `jd auth login` to establish a fresh session","Re-run the verify command after re-login"],"exampleFix":"// before\nawait jdWhoami(); // fails with empty pin cookie\n// after\nawait clearCookies({ domain: '.jd.com' });\nawait jdAuthLogin();\nconst me = await jdWhoami();","handlingStrategy":"try-catch","validationCode":"const pin = (await page.getCookies({ url: 'https://www.jd.com' }))\n  .find(c => c.name === 'pin');\nif (!pin || !pin.value || !decodeURIComponent(pin.value)) {\n  await clearCookies({ domain: '.jd.com' });\n  await jdAuthLogin();\n}","typeGuard":"function hasValidPin(cookies) {\n  const pin = cookies.find(c => c.name === 'pin');\n  return !!pin && !!pin.value && !!decodeURIComponent(pin.value);\n}","tryCatchPattern":"try {\n  await jdVerify();\n} catch (e) {\n  if (e.code === 'AUTH_REQUIRED' && /empty after decode/.test(e.detail || e.message)) {\n    await clearCookies({ domain: '.jd.com' });\n    await jdAuthLogin();\n  } else throw e;\n}","preventionTips":["Re-login rather than trusting a present-but-empty pin cookie","Clear JD cookies on AUTH_REQUIRED before retrying login","Periodically refresh JD sessions in long-running automation","Log out/in cleanly instead of keeping half-expired cookies"],"tags":["auth","jd","cookies","stale-session"],"backgroundTag":"site-session-not-logged-in","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}