You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Puppeteer报‘Requesting main frame too early!’错误致浏览器关闭的排查与解决

Puppeteer检查登录状态函数的「Requesting main frame too early!」问题

我用Puppeteer写了一个检查用户登录状态的函数:

export async function checkIfUserIsLoggedIn() {
  const logger = getLogger('checkIfUserIsLoggedIn()');
  try {
    if (!page || !browser) {
      logger.info('page or browser is not open');
      return false;
    }

    logger.info('page or browser is open');
    await delay(randomWaitTimeSeconds1_2());

    // await page.waitForSelector(selector);
    const btn = await page.$(selector);

    logger.info(`user is logged in - ${!!btn ? 'YES' : 'NO'}`);
    return !!btn;
  } catch (e) {
    logError('checkIfUserIsLoggedIn()', e);
  }
}

这个函数偶尔会触发「Error: Requesting main frame too early!」错误,完整报错如下:

[2023-10-02T01:58:06.825] [ERROR] checkIfUserIsLoggedIn() - Error: Requesting main frame too early!
    at assert (C:\Users\simon\Desktop\tb-project-pup\node_modules\puppeteer-core\lib\cjs\puppeteer\util\assert.js:28:15)
    at FrameManager.mainFrame (C:\Users\simon\Desktop\tb-project-pup\node_modules\puppeteer-core\lib\cjs\puppeteer\cdp\FrameManager.js:219:32)
    at CdpPage.mainFrame (C:\Users\simon\Desktop\tb-project-pup\node_modules\puppeteer-core\lib\cjs\puppeteer\cdp\Page.js:407:35)
    at CdpPage.$ (C:\Users\simon\Desktop\tb-project-pup\node_modules\puppeteer-core\lib\cjs\puppeteer\api\Page.js:324:31)
    at checkIfUserIsLoggedIn (file:///C:/Users/simon/Desktop/tb-project-pup/main/checkIfUserIsLoggedIn.js:19:38)

这个错误会直接导致Puppeteer关闭浏览器,但其他错误比如TimeoutError、ProtocolError不会触发浏览器关闭。我推测是页面内置定时器触发的自动重载(带?reload=auto参数)导致的,这种情况很少发生。

我想搞清楚两个问题:

  1. 为什么这个错误会导致浏览器关闭?
  2. 怎么正确解决这个问题?

我自己考虑过两个方案:

  • 在const btn = await page.$(selector);前加await page.waitForNavigation({ waitUntil: 'domcontentloaded', });,但页面重载间隔可能超过2分钟,这样等太久不现实;
  • 加重试逻辑,比如下面这段代码,但不确定要不要保留原来的try/catch:
const anchorElement = await page.$(selector).catch(async () => {
      retryCount++;
      if (retryCount < 3) {
        await checkIfUserIsLoggedIn();
       // OR await page.$(selector)
      }
    });

问题解答

1. 为什么这个错误会导致浏览器关闭?

这个错误来自Puppeteer内部的断言失败(assert函数抛出的错误)。当页面正在重载时,FrameManager还没完成主框架的初始化,此时调用page.$()会触发主框架获取操作,触发断言失败。这类内部断言错误属于Puppeteer认为的严重状态异常,会导致CDP(Chrome DevTools Protocol)连接中断,进而触发浏览器进程关闭——不同于普通的API错误(比如超时、协议错误),内部断言失败意味着Puppeteer的状态已经和浏览器不同步,无法继续正常交互,所以会直接关闭浏览器。

2. 正确的解决方案

推荐采用带重试的异常捕获+等待页面稳定的组合方案,同时保留原有try/catch来处理其他错误,针对特定错误做重试:

优化后的代码

export async function checkIfUserIsLoggedIn(retryCount = 0) {
  const logger = getLogger('checkIfUserIsLoggedIn()');
  const MAX_RETRIES = 3;
  
  try {
    if (!page || !browser) {
      logger.info('page or browser is not open');
      return false;
    }

    // 先检查页面是否处于导航状态,避免在重载时操作
    if (page.isNavigationPending()) {
      logger.info('Page is navigating, waiting for completion...');
      // 等待导航完成,设置合理超时(比如10秒,比正常重载时间短)
      await page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 10000 }).catch(() => {
        logger.info('Navigation timed out, proceeding with check');
      });
    }

    logger.info('page or browser is open');
    await delay(randomWaitTimeSeconds1_2());

    const btn = await page.$(selector);

    logger.info(`user is logged in - ${!!btn ? 'YES' : 'NO'}`);
    return !!btn;
  } catch (e) {
    logError('checkIfUserIsLoggedIn()', e);
    
    // 针对特定错误做重试
    if (e.message.includes('Requesting main frame too early!') && retryCount < MAX_RETRIES) {
      logger.info(`Retrying login check (${retryCount + 1}/${MAX_RETRIES})...`);
      // 等待一小段时间让页面完成重载初始化
      await delay(1000);
      return checkIfUserIsLoggedIn(retryCount + 1);
    }
    
    // 其他错误直接返回false或抛出(根据业务需求)
    return false;
  }
}

方案说明

  • 保留原有try/catch:用来统一捕获所有错误,同时针对特定的「Requesting main frame too early!」错误做重试逻辑,其他错误按原有逻辑处理;
  • 检查导航状态:通过page.isNavigationPending()提前判断页面是否正在重载,避免在不稳定状态下执行DOM查询;
  • 有限重试:设置最大重试次数(比如3次),避免无限循环,每次重试前等待1秒让页面完成主框架初始化;
  • 合理超时的导航等待:如果页面正在导航,等待10秒超时,避免因为超长重载时间阻塞流程。

另外,也可以考虑监听页面的framenavigated事件,提前感知页面重载,在重载完成后再执行登录状态检查,但对于偶尔发生的自动重载,上述重试方案已经足够简洁有效。


内容的提问来源于stack exchange,提问作者Adrian Kato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 19:50:17