Artisan のトラブルシューティング
ブリッジの障害はすべて、型付き例外として表面化します。例外とメッセージを以下の表と照合してください。各行は該当するソース側のチェックを正確に示しているため、症状ではなく原因を修正できます。
例外による診断
「例外による診断」という見出しのセクションChromeNotAvailableException
「ChromeNotAvailableException」という見出しのセクション
chrome-php/chrome is not installed. Install it via: composer require chrome-php/chrome:^1.15
CDP クライアントライブラリがオートローダーに登録されていません。BrowserPool::getBrowser() は、Chrome を起動する前にこの例外を発生させます。インストールコマンドを実行してください。これはバイナリの欠落とは別の問題です。ライブラリのチェックとバイナリのチェックは、別々の段階で実行されます。
ChromeRenderException — 起動またはタイムアウト
「ChromeRenderException — 起動またはタイムアウト」という見出しのセクション
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 依存パッケージ一式をインストールしてください。
ChromeRenderException — 出力が空
「ChromeRenderException — 出力が空」という見出しのセクション
Chrome printToPDF returned empty data
Chrome は起動しましたが、printToPDF が 0 バイトを返しました。よくある原因は、レンダリング対象のボックスを生成しない入力(空の body、すべてのコンテンツが display:none)、または印刷中の Chrome のクラッシュです。その HTML が可視のボックスとしてレンダリングされることを確認してください。ホストのメモリ逼迫(メモリプレッシャー)も確認してください。
RuntimeException — Chrome 呼び出し前に入力が拒否された
「RuntimeException — Chrome 呼び出し前に入力が拒否された」という見出しのセクション| メッセージに含まれる文字列 | 原因 | 対処 |
|---|---|---|
exceeds maximum allowed size | HTML が maxHtmlSize の上限を超過 | 入力の縮小、または max_html_size の引き上げ(リソース枯渇の攻撃面が広がります) |
oversized base64 data URI | インライン base64 が 13 MB 以上 | 埋め込みアセットの縮小、より小さい画像の参照 |
forbidden meta refresh redirect | <meta http-equiv="refresh"> が存在 | そのタグの削除(SSRF のナビゲーションベクトルであるため常に拒否) |
これらは ChromeSecurityPolicy::validate() に由来し、Chrome に接続する前に発生するため、テストで高速かつ低コストに再現できます。
PdfParseException
「PdfParseException」という見出しのセクション
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/. を参照してください。
約 100 回のレンダリングごとにレイテンシが急増する
「約 100 回のレンダリングごとにレイテンシが急増する」という見出しのセクションこれは想定どおりの動作です。BrowserPool は、メモリ使用量を抑えるために 100 回のレンダリングごとに Chrome を再起動します。notice レベルのログ行には、レンダリング回数とともに再起動が記録されます。これはインシデントではなく、SLO 上の既知の定期的なコストとして扱ってください。再起動頻度が 100 回のレンダリングごとより高い場合は、想定より重いドキュメントであることを意味します。
長時間のバッチでメモリが増加する
「長時間のバッチでメモリが増加する」という見出しのセクションBrowserPool は 100 回のレンダリングごとの再起動で増加を抑えますが、非常に長時間稼働するワーカーでは、依然としてメモリが蓄積する場合があります。大きなバッチの合間に close() を呼び出して Chrome プロセスを早めにリサイクルし、ワーカーはホストのメモリ制限内で実行してください。
診断チェックリスト
「診断チェックリスト」という見出しのセクション- 入力と環境を切り分けるため、信頼できる最小限の HTML フラグメントで再現してください。
- ホスト上で、ワーカーのユーザーとして
chromium --headless --dump-dom about:blankを実行してください。 - PSR-3 ロガーを注入し、
info/notice行(バイナリのパス、再起動回数)を確認してください。 - 次の点を確認してください。
chrome-php/chromeがインストール済みであること。これは、BrowserPool::getBrowser()がChromeNotAvailableExceptionをスローしないことで確認できます。 - Chrome 側の根本原因については、例外の previous exception を確認してください。
- /integrations/artisan/install/(インストール)
- /integrations/artisan/configuration/(設定)
- /integrations/artisan/security-and-operations/(セキュリティと運用)
- /integrations/artisan/chrome-renderer-setup/(Chrome レンダラーのセットアップ)
- /integrations/artisan/production-usage/(本番環境での使用)