トラブルシューティング
ブリッジは 3 種類の例外を送出します。キャッチした例外は、何が失敗したか、リトライまたはフォールバックが適切かどうかを示します。以下のメッセージ断片は、すべてソースから引用したものです。
例外の階層
「例外の階層」という見出しのセクション| 例外 | 継承元 | 意味 |
|---|---|---|
CloudflareNotAvailableException | NextPDF\Exception\NextPdfException | エッジに到達できなかった、または設定が不完全で、利用可能なフォールバックが存在しない状態。 |
CloudflareRenderException | NextPDF\Exception\NextPdfException | Worker は応答したものの、レンダリングが失敗した状態(HTTP エラーまたは不正な形式のボディ)。フォールバックは決して行いません。 |
InvalidSpkiPinException | InvalidArgumentException | 設定された SPKI ピン文字列が不正な形式である状態。 |
CloudflareSecurityPolicy は、入力および URL ポリシー違反に対して RuntimeException を直接送出します。これは、いかなるリクエストを送信するよりも前に行われます。
設定および入力の失敗
「設定および入力の失敗」という見出しのセクション| メッセージ断片 | 送出元 | 原因 | 対処 |
|---|---|---|---|
incomplete (missing worker_url or api_token) | Renderer(フォールバック経路経由) | workerUrl または apiToken が空 | 両方を設定し、isValid() で検証 |
HTML input exceeds maximum size | CloudflareSecurityPolicy::validate() | HTML が maxHtmlSize を超過 | 入力を減らすか、maxHtmlSize を意図的に引き上げ |
Base64 data URI exceeds safety limit | CloudflareSecurityPolicy::validate() | data:;base64, URI が推定で 13631488 バイトを超過 | アセットを外部化し、大きなバイナリはインライン化しない |
meta-refresh redirect which could cause SSRF | CloudflareSecurityPolicy::validate() | <meta http-equiv="refresh"> タグ | タグを削除し、レンダリング対象の HTML の外側でサーバーサイドのリダイレクトを使用 |
Invalid Worker URL | validateWorkerUrl() | URL を解析できない、または scheme/host が欠落 | 完全な絶対 HTTPS URL の指定 |
Worker URL must use HTTPS | validateWorkerUrl() | HTTPS 以外のスキーム | https:// の使用 |
private or reserved IP addresses | validateWorkerUrl() | RFC 1918/ループバック/RFC 3927 の範囲内の IP リテラル | パブリックなエンドポイントを指す設定 |
hostname resolves to a private or reserved IP | validateWorkerUrl() | 解決された A/AAAA レコードが private/reserved | DNS の修正と、リバインディングの可能性の調査 |
DNS answer changed since validation | assertPinsStillValid() | チェックと送信の間にホストが新しい IP へ解決 | 再解決し、リバインディングの試みの可能性として扱う |
Worker 側の失敗
「Worker 側の失敗」という見出しのセクションこれらは CloudflareRenderException です。Worker は応答しましたが、レンダリング自体が失敗しています。これらはローカルフォールバックを決してトリガーしません。エッジには到達できていたためです。
| メッセージ断片 | 原因 |
|---|---|
Cloudflare Worker returned HTTP <code>: <detail> | 200 以外のステータス。詳細は JSON の error フィールド、またはボディの先頭 200 バイト。 |
Worker returned empty or invalid PDF data | %PDF で始まらないバイナリ応答。 |
Worker error: <message> | error フィールドを持つ JSON 応答。 |
JSON response missing "pdf" field | pdf フィールドのない JSON 応答。 |
Invalid base64-encoded PDF in JSON response | pdf フィールドを Base64 デコードしても、%PDF で始まるバイト列にならない状態。 |
Invalid JSON response from Worker | Content-Type: application/json でありながら、ボディが配列にデコードされない状態。 |
Unexpected Content-Type from Worker: <type> | Content-Type が application/pdf でも application/json でもない 200 応答。 |
これらのいずれかをキャッチした場合は、Worker のログを確認してください。失敗は Worker 側にあり、このブリッジ内ではありません。
到達性およびフォールバックの失敗
「到達性およびフォールバックの失敗」という見出しのセクションこれらは CloudflareNotAvailableException です。エッジを使用できず、どのフォールバックも PDF を生成しなかった場合です。
| メッセージ断片 | 原因 | 対処 |
|---|---|---|
Cloudflare Worker unavailable: <reason> | トランスポートエラー、フォールバック無効 | fallbackToLocal を有効化してファクトリーを配線するか、接続性を修正 |
Artisan is installed but no LocalRendererFactoryInterface was provided | nextpdf/artisan は存在するが、ファクトリーが渡されていない | コンストラクターに LocalRendererFactoryInterface を渡す |
local Chrome fallback (nextpdf/artisan) is not installed | フォールバック有効、ファクトリーなし、Artisan 不在 | composer require nextpdf/artisan を実行し、ファクトリーを配線 |
PSR-3 ロガーを供給していて、フォールバック経路が実行されると、ブリッジは warning(Cloudflare render failed, attempting fallback)を記録し、続いて info(Falling back to local renderer)を記録します。
トランスポート/ピンニングの失敗
「トランスポート/ピンニングの失敗」という見出しのセクション| 症状 | 原因 | 対処 |
|---|---|---|
InvalidSpkiPinException: Invalid SPKI pin format | sha256/<base64>(または sha256//<base64>)形式ではないピン | ピン文字列の修正 |
cURL transport error (<n>): <msg> | cURL レベルの失敗(TLS、DNS、タイムアウト) | cURL のエラー番号を確認。ピンが設定されている場合は、配信されている SPKI が引き続きピン留め対象かを確認 |
| 証明書のローテーション直後にレンダリングが即座に失敗する | 新しい証明書の SPKI がピンセットに含まれていない | ローテーションの前に新しい SPKI をバックアップピンとして追加します。 |
| ピンが設定されているにもかかわらず、ピン留めトランスポートが使用されない | PSR-17 の ResponseFactory が供給されていない | ResponseFactory を渡します。ピン留めトランスポートにはこれが必要です。 |
isAvailable() の挙動
「isAvailable() の挙動」という見出しのセクションisAvailable() は決して例外を送出しません。設定が無効な場合、または HEAD プローブが失敗するか例外を送出した場合は、false を返します。プローブがステータス 500 未満で応答した場合にのみ true を返します。true という結果はあくまでヒントにすぎません。後続の POST は、上記の Worker 側エラーのいずれによっても依然として失敗しうるためです。プローブの成功を保証として扱わないでください。
レート制限の意外な挙動
「レート制限の意外な挙動」という見出しのセクションApiProtection のリミッターは、プロセスごとのインメモリです。カウントは再起動をまたいで保持されず、ワーカーやノード間で共有されることもありません。そのため、同じクライアントがあるノードでは許可され、別のノードでは拒否される場合があっても、想定どおりの挙動です。クラスター全体で制限するには、共有ストアでリミッターをフロントエンド化してください。
- /integrations/cloudflare/security-and-operations/ — 運用ランブックと、これらのメッセージの背景にある制御。
- /integrations/cloudflare/quickstart/ — 標準的な try/catch パターン。
- /integrations/cloudflare/production-usage/ — フォールバック配線の詳細。