🌎

PuppeteerでProtocol Errorが発生したときの対処法

に公開

Flutterで開発中のアプリにおいて、Puppeteerを使ってWebページを操作しています。このとき、以下のエラーがたびたび発生しました。

Protocol error (Page.navigate): Session closed. Most likely the page has been closed.

このエラーに対する対処法を調べましたので、共有します。私の場合は定期的なページのリフレッシュで解決しました。

エラーの原因(結論)

このエラーは、メモリー不足が原因で発生していました。

エラーメッセージそのものは、Puppeteerが操作しようとしているページが既に閉じられていることを示しています。しかし、コード上ではページを閉じる操作は行っていません。

一方で、まれにPage crashed!というエラーが報告されることもありました。

結局、これはPuppeteerのページオブジェクトが抱え込むデータが肥大することが原因でメモリ不足に陥ったことから起きる問題でした。

私のアプリケーションではページオブジェクトを作ってそのうえでページ遷移を行います。運の悪いことに対象のWebページが非常に重く、何らかのデータをブラウザにどんどん抱え込ませるタイプだったようです。

対処法

この問題に対して、定期的にページオブジェクトを破棄して新しいページオブジェクトを作成することで対処しました。

    for (var target in source) {
      if (count < 0) {
        // pageLife回に一度ページをリセット
        await page.close();
        page = await createPage(browser);
        count = pageLife;
      } else {
        count--;
      }

      String result = await get(page, target);
    }

このコードでは、pageLife回の操作を行った後にページオブジェクトを閉じて新しいページオブジェクトを作成しています。これにより、メモリ使用量が一定以上に膨れ上がるのを防ぎ、エラーの発生を抑制しました。

この方法で、私のアプリケーションではエラーが発生しなくなりました。

補足

このエラーについて検索すると、「shared memory領域不足が原因なので--disable-dev-shm-usageをヘッドレス・ブラウザに渡せ。これでshared memoryを使わなくなる」という情報が見つかりました。

そこで試してみました。

Future<Browser> initializeBrowser() async {
  return await puppeteer.launch(
    headless: true,
    args: [
      '--no-sandbox',
      '--disable-dev-shm-usage',
    ],
  );
}

メモリ不足を解消するという意味では正しい方向だと思うのですが、私が対象としていたWebページが重すぎたのか、これでは解決に至りませんでした。

結局、--disable-dev-shm-usageは指定せず、先に示したページのリフレッシュで解決しました。

Discussion