コンテンツにスキップ

Artisan のトラブルシューティング

ブリッジの障害はすべて、型付き例外として表面化します。例外とメッセージを以下の表と照合してください。各行は該当するソース側のチェックを正確に示しているため、症状ではなく原因を修正できます。

chrome-php/chrome is not installed. Install it via: composer require chrome-php/chrome:^1.15

CDP クライアントライブラリがオートローダーに登録されていません。BrowserPool::getBrowser() は、Chrome を起動する前にこの例外を発生させます。インストールコマンドを実行してください。これはバイナリの欠落とは別の問題です。ライブラリのチェックとバイナリのチェックは、別々の段階で実行されます。

Chrome renderer failed: <cause>

Chrome を起動できなかった、タイムアウトした、またはクラッシュした状態です。直前の例外(previous exception)に元の原因が保持されています。よくある原因は次のとおりです。

  • バイナリが見つからない/実行できない。 chromium --headless --dump-dom about:blank で確認してください。chrome_binary には絶対パスを設定してください。
  • サンドボックスを初期化できない(コンテナ環境)。 原因にサンドボックスまたは名前空間(namespace)が示されています。サンドボックスに対応したコンテナをプロビジョニングする(推奨)か、no_sandbox: true を設定してください(設定前に /integrations/artisan/security-and-operations/. を参照してください)。
  • タイムアウト。 重いドキュメントが render_timeout を超過しました。そのワークロードについてタイムアウトを引き上げるか、ドキュメントを縮小してください。ユーザーに公開されるパスでは、サービス拒否(DoS)とのトレードオフを考慮してください。
  • 共有ライブラリの欠落。 Chrome がただちに終了します。使用しているディストリビューションの Chrome 依存パッケージ一式をインストールしてください。

Chrome printToPDF returned empty data

Chrome は起動しましたが、printToPDF が 0 バイトを返しました。よくある原因は、レンダリング対象のボックスを生成しない入力(空の body、すべてのコンテンツが display:none)、または印刷中の Chrome のクラッシュです。その HTML が可視のボックスとしてレンダリングされることを確認してください。ホストのメモリ逼迫(メモリプレッシャー)も確認してください。

メッセージに含まれる文字列原因対処
exceeds maximum allowed sizeHTML が maxHtmlSize の上限を超過入力の縮小、または max_html_size の引き上げ(リソース枯渇の攻撃面が広がります)
oversized base64 data URIインライン base64 が 13 MB 以上埋め込みアセットの縮小、より小さい画像の参照
forbidden meta refresh redirect<meta http-equiv="refresh"> が存在そのタグの削除(SSRF のナビゲーションベクトルであるため常に拒否)

これらは ChromeSecurityPolicy::validate() に由来し、Chrome に接続する前に発生するため、テストで高速かつ低コストに再現できます。

Page <n> has no content stream

Chrome が生成した PDF から、パーサーがページを抽出できませんでした。これはまれなケースで、Chrome の出力が不正であるか、想定外の構造を出力する Chrome バージョンであることを示しています。Chrome のバージョンと入力を記録してください。そのバイナリがサポート対象の Chrome/Chromium ビルドであることを確認してください。

これはバグではありません。ブリッジはサブリソースの取得をすべてブロックします(CSP default-src 'none' に加えて、CDP の setBlockedURLs('*') によるブロック)。リモートの <img>、スタイルシート、フォント、スクリプト、iframe は読み込まれません。アセットは data: URI としてインライン化し、CSS は defaultCss または <style> でインライン化してください。ネットワークモデルについては /integrations/artisan/security-and-operations/. を参照してください。

ドキュメントが Chrome の 2 ページ目にはみ出し、ブリッジは 0 ページ目のみをインポートしました。自動フィット用のバッファが、通常より大きいリフローに対して小さすぎたか、明示的に指定した高さが小さすぎた可能性があります。コンテンツに合わせた高さを明示的に指定するか、明示的な高さを削除して、安全バッファ付きの自動フィットを使用してください。高さの扱いについては /integrations/artisan/production-usage/. を参照してください。

これは想定どおりの動作です。BrowserPool は、メモリ使用量を抑えるために 100 回のレンダリングごとに Chrome を再起動します。notice レベルのログ行には、レンダリング回数とともに再起動が記録されます。これはインシデントではなく、SLO 上の既知の定期的なコストとして扱ってください。再起動頻度が 100 回のレンダリングごとより高い場合は、想定より重いドキュメントであることを意味します。

BrowserPool は 100 回のレンダリングごとの再起動で増加を抑えますが、非常に長時間稼働するワーカーでは、依然としてメモリが蓄積する場合があります。大きなバッチの合間に close() を呼び出して Chrome プロセスを早めにリサイクルし、ワーカーはホストのメモリ制限内で実行してください。

  1. 入力と環境を切り分けるため、信頼できる最小限の HTML フラグメントで再現してください。
  2. ホスト上で、ワーカーのユーザーとして chromium --headless --dump-dom about:blank を実行してください。
  3. PSR-3 ロガーを注入し、info/notice 行(バイナリのパス、再起動回数)を確認してください。
  4. 次の点を確認してください。chrome-php/chrome がインストール済みであること。これは、BrowserPool::getBrowser()ChromeNotAvailableException をスローしないことで確認できます。
  5. Chrome 側の根本原因については、例外の previous exception を確認してください。
  • /integrations/artisan/install/(インストール)
  • /integrations/artisan/configuration/(設定)
  • /integrations/artisan/security-and-operations/(セキュリティと運用)
  • /integrations/artisan/chrome-renderer-setup/(Chrome レンダラーのセットアップ)
  • /integrations/artisan/production-usage/(本番環境での使用)