Puppeteer出现‘Protocol error (Runtime.callFunctionOn): Target closed’错误原因排查
问题描述
我是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

