{"record":{"id":"2eb5bbe20fd18769","repo":"jackwener/OpenCLI","slug":"redirected-away-from-creator-center-session-may","errorCode":null,"errorMessage":"Redirected away from creator center — session may have expired. Re-capture browser login via: opencli xiaohongshu creator-profile","messagePattern":"Redirected away from creator center — session may have expired\\. Re-capture browser login via: opencli xiaohongshu creator-profile","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/publish.js","lineNumber":1220,"sourceCode":"            throw new ArgumentError(`Title is ${title.length} chars — must be ≤ ${MAX_TITLE_LEN}`);\n        if (!content)\n            throw new ArgumentError('Positional argument <content> is required');\n        if (!isTextImage && imagePaths.length === 0)\n            throw new ArgumentError('Provide --card-text (text-image mode) or --images (upload mode); neither was given.');\n        if (imagePaths.length > MAX_IMAGES)\n            throw new ArgumentError(`Too many images: ${imagePaths.length} (max ${MAX_IMAGES})`);\n        // The editor-page image input (text-image append) rejects gif.\n        if (isTextImage && imagePaths.some((p) => path.extname(p).toLowerCase() === '.gif'))\n            throw new ArgumentError('文字配图模式追加的图片不支持 .gif（编辑器图片入口只接受 jpg/jpeg/png/webp）');\n        // Validate image paths before navigating (fast-fail on bad paths / unsupported formats)\n        const absImagePaths = validateImagePaths(imagePaths);\n        // ── Step 1: Navigate to publish page ──────────────────────────────────────\n        await page.goto(PUBLISH_URL);\n        await page.wait({ time: 3 });\n        // Verify we landed on the creator site (not redirected to login)\n        const pageUrl = await page.evaluate('() => location.href');\n        if (!pageUrl.includes('creator.xiaohongshu.com')) {\n            throw new Error('Redirected away from creator center — session may have expired. ' +\n                'Re-capture browser login via: opencli xiaohongshu creator-profile');\n        }\n        // ── Step 2: Select 图文 (image+text) note type if tabs are present ─────────\n        const tabResult = await selectImageTextTab(page);\n        const surface = await waitForPublishSurfaceState(page, tabResult?.ok ? 5_000 : 2_000);\n        if (surface.state === 'video_surface') {\n            await page.screenshot({ path: '/tmp/xhs_publish_tab_debug.png' });\n            const detail = tabResult?.ok\n                ? `clicked \"${tabResult.text}\"`\n                : `visible candidates: ${(tabResult?.visibleTexts || []).join(' | ') || 'none'}`;\n            throw new Error('Still on the video publish page after trying to select 图文. ' +\n                `Details: ${detail}. Debug screenshot: /tmp/xhs_publish_tab_debug.png`);\n        }\n        // ── Step 3: Acquire images — text-image generation and/or upload ──────────\n        let appliedCardStyle = cardStyle;\n        if (isTextImage) {\n            // Drive 文字配图: type cards → 生成图片 → pick style → 下一步 → standard editor.\n            appliedCardStyle = await runTextImageFlow(page, cards, cardStyle);","sourceCodeStart":1202,"sourceCodeEnd":1238,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/publish.js#L1202-L1238","documentation":"Thrown during the first step of the xiaohongshu publish automation after page.goto(PUBLISH_URL). The CLI checks location.href and expects it to contain creator.xiaohongshu.com; if the site redirected elsewhere (typically the login page), the stored browser session is considered dead, so publishing cannot proceed.","triggerScenarios":"Navigating to the publish URL lands on a non-creator host (login wall, verify page, or redirect to www.xiaohongshu.com) because the persisted browser login is missing or expired.","commonSituations":"Expired xiaohongshu session cookies, running the publish command on a machine/profile where 'opencli xiaohongshu creator-profile' was never run, xiaohongshu forcing re-authentication or captcha, or a proxy/network change invalidating the session.","solutions":["Run 'opencli xiaohongshu creator-profile' to re-capture an interactive browser login, then retry publish.","Verify network/proxy settings are not blocking creator.xiaohongshu.com.","Log in manually in a normal browser to clear any security verification/captcha on the account, then re-capture.","Wait and retry later if xiaohongshu is rate-limiting or challenging the account."],"exampleFix":"// before\nopencli xiaohongshu publish --title \"hi\" --images a.png\n// after\nopencli xiaohongshu creator-profile   # re-capture login first\nopencli xiaohongshu publish --title \"hi\" --images a.png","handlingStrategy":"retry","validationCode":"// before publishing, verify the captured profile is still valid\nconst url = await page.evaluate('() => location.href');\nif (!url.includes('creator.xiaohongshu.com')) {\n  console.error('Session dead — run: opencli xiaohongshu creator-profile');\n  process.exit(1);\n}","typeGuard":"function isCreatorUrl(url) {\n  return typeof url === 'string' && url.includes('creator.xiaohongshu.com');\n}","tryCatchPattern":"try {\n  await publish(opts);\n} catch (e) {\n  if (String(e.message).includes('session may have expired')) {\n    execSync('opencli xiaohongshu creator-profile');\n    return publish(opts); // retry once after re-login\n  }\n  throw e;\n}","preventionTips":["Re-run 'opencli xiaohongshu creator-profile' periodically or when publish fails with this error.","Don't share the captured browser profile across machines with different network/proxy setups.","Log in manually first if the account recently triggered xiaohongshu security checks.","Handle long-running jobs by re-validating the session before each publish batch."],"tags":["authentication","session-expired","browser-automation","xiaohongshu"],"backgroundTag":"browser-session-expired","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}