{"record":{"id":"bb767ab8bc6dfd46","repo":"jackwener/OpenCLI","slug":"2-bb767a","errorCode":null,"errorMessage":"登录超时（2分钟），请手动登录后重试","messagePattern":"登录超时（2分钟），请手动登录后重试","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/wechat-channels/publish.js","lineNumber":616,"sourceCode":"        process.stderr.write(\n          '\\n⚠️  未登录视频号。已跳转到登录页，请在 Chrome 中扫码登录...\\n' +\n          '   登录完成后将自动继续发布。\\n\\n'\n        );\n\n        const loginDeadline = Math.min(deadline, Date.now() + 120_000);\n        let loggedIn = false;\n        while (Date.now() < loginDeadline) {\n          await page.wait({ time: 3 });\n          const url = await evalPage(page, '() => location.href');\n          if (!url.includes(LOGIN_PATH_FRAGMENT)) {\n            loggedIn = true;\n            break;\n          }\n          process.stderr.write('   等待扫码中...\\n');\n        }\n\n        if (!loggedIn) {\n          throw new AuthRequiredError('channels.weixin.qq.com', '登录超时（2分钟），请手动登录后重试');\n        }\n\n        process.stderr.write('✅ 登录成功，继续发布...\\n\\n');\n        await page.wait({ time: 3 }); // let bridge stabilize after login redirect\n        await page.goto(PUBLISH_URL);\n        await page.wait({ time: 5 });\n      }\n    }\n\n    // ── 4. Upload video ──────────────────────────────────────────────────\n    await uploadFile(page, videoPath);\n    await page.wait({ time: 2 });\n\n    // ── 5. Wait for upload + transcode done ──────────────────────────────\n    await waitForUploadDone(page, path.basename(videoPath), Math.min(180_000, remainingMs(deadline, '视频上传/转码')));\n    await page.wait({ time: 1 });\n\n    // ── 6. Fill title (主要内容) ─────────────────────────────────────────","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/wechat-channels/publish.js#L598-L634","documentation":"If the automated login-wait loop cannot detect a logged-in weixin.qq.com session within 2 minutes, the command throws AuthRequiredError telling the user to log in manually. It is an authentication timeout, not a publish failure.","triggerScenarios":"The polling loop never observed loggedIn=true before the 2-minute deadline: QR code not scanned, session cookie invalid, or login page redirected somewhere the loop does not detect.","commonSituations":"User did not scan the QR code in time; WeChat flagged the login and required extra verification; stale/expired cookies caused a login loop; headless environment where scanning is impossible.","solutions":["Scan the QR code promptly after the command starts, or pre-login via a persistent session (--site-session persistent)","Run with persistent session, log in manually once in the browser, then re-run the command","Increase the login wait window if 2 minutes is too short for your workflow","Verify cookies are valid (not expired) before starting the publish"],"exampleFix":"// before\nawait cli.run('publish', { video: 'v.mp4' }); // fresh session, QR wait\n// after\nawait cli.run('login', { siteSession: 'persistent' }); // one-time manual login\nawait cli.run('publish', { video: 'v.mp4', siteSession: 'persistent' });","handlingStrategy":"retry","validationCode":"// pre-check for an existing session before starting the QR wait\nconst hasSession = await page.evaluate(() => document.cookie.includes('SESSDATA') || location.hostname !== 'channels.weixin.qq.com');","typeGuard":null,"tryCatchPattern":"try {\n  await publishCmd(page, kwargs);\n} catch (e) {\n  if (e instanceof AuthRequiredError && /登录超时/.test(e.message)) {\n    console.error('QR login timed out — log in via persistent session and retry.');\n    // e.g. await runLogin(page); then retry once\n  } else throw e;\n}","preventionTips":["Use a persistent session and log in manually once beforehand","Scan the QR code promptly after the command starts","Keep cookies fresh; re-login when they expire","Allow extra time in headless or slow-network environments"],"tags":["auth","login-timeout","wechat-channels"],"backgroundTag":"login-timeout","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}