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

Puppeteer出现‘Protocol error (Runtime.callFunctionOn): Target closed’错误原因排查

Puppeteer在Bun环境下的TargetCloseError排查方向

问题描述

我是Puppeteer新手,正在用它做E2E测试,运行环境是Bun v0.6.9,官方文档说明Puppeteer可在Bun中正常运行,但执行以下测试代码时出现无法解决的错误:

describe('A test', async () => {

  const browser = await puppeteer.launch({ defaultViewport: null, headless: false })

  const page = await browser.newPage()

  beforeEach(async () => await page.goto('http://localhost:3000'))
  afterEach(async () => await page.close())
  afterAll(async () => await browser.close())

  it('should learn puppeteer', async () => {

    console.log(page.url())                  // 正常输出:http://localhost:3000/

    const source = await page.content();
    console.log(source)                     // 正常输出页面内容

    page
      .click('input[type="submit"]')
      .then(() => console.log('got it'))
      .catch((e) => console.log(e))        // 抛出错误

    console.log('this line is logged')     // 正常输出
    expect(1).toBe(1)                      // 测试通过
  })
})

错误信息:

34 |     /**
35 |      * @internal
36 |      */
37 |     constructor(message) {
38 |         super(message);
39 |         this.name = this.constructor.name;
                ^
TargetCloseError: Protocol error (Runtime.callFunctionOn): Target closed
 code: "undefined"

      at /Users/charnould/GitHub/malro/node_modules/puppeteer-core/lib/esm/puppeteer/common/Errors.js:39:13

注:网页http://localhost:3000中确实存在<input type="submit" value="Login">元素。

排查方向

  • 异步操作未等待,页面被提前关闭
    你代码里的page.click()用了.then/.catch但没有加await,测试执行到expect(1).toBe(1)就结束了,紧接着afterEach会执行page.close()。这时候page.click()的异步操作还没完成,页面已经被关闭,直接触发TargetCloseError。
    解决方法:给page.click()加上await,改用try/catch处理错误:

    try {
      await page.click('input[type="submit"]');
      console.log('got it');
    } catch (e) {
      console.log(e);
    }
    
  • 测试生命周期配置错误
    你把browser和page的初始化放在了describe块的顶层,afterEach每次测试后都会关闭page,但beforeEach只是跳转页面,没有重新创建page。虽然当前只有一个测试,但结合异步问题,测试结束后关闭page会导致未完成的点击操作报错。
    正确的做法是把page的创建放在beforeEach里,确保每次测试都用全新的page:

    describe('A test', () => {
      let browser;
    
      beforeAll(async () => {
        browser = await puppeteer.launch({ defaultViewport: null, headless: false });
      });
    
      let page;
      beforeEach(async () => {
        page = await browser.newPage();
        await page.goto('http://localhost:3000');
      });
    
      afterEach(async () => {
        await page.close();
      });
    
      afterAll(async () => {
        await browser.close();
      });
    
      // 测试用例...
    })
    
  • Bun与Puppeteer版本兼容性问题
    你使用的Bun v0.6.9是较旧的版本,可能和当前Puppeteer版本存在兼容性问题。建议升级Bun到最新稳定版,或者查看Puppeteer官方文档确认支持的Bun版本范围。

  • 页面跳转未等待导致目标异常关闭
    点击submit按钮后页面可能会跳转,如果没有等待跳转完成,也可能触发TargetCloseError。可以尝试同时等待点击和导航完成:

    await Promise.all([
      page.waitForNavigation(),
      page.click('input[type="submit"]')
    ]);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 12:32:03