コンテンツにスキップ

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

ブリッジは明確かつ早期に失敗します。いずれの失敗も型付き例外であり、メッセージで原因が分かるようになっています。このページは、それらを一覧化したカタログです。各失敗について、例外の型、表示されるメッセージの断片、コードパス上の正確なトリガー、修正方法を示します。

例外のファミリーは次のとおりです。

  • GotenbergConvertException — 変換レイヤーの失敗(設定、トランスポート、またはレスポンス)。
  • RuntimeException — ネットワーク通信が発生する前に、セキュリティポリシーが送出する検証レイヤーの失敗。
  • ValueError — 認識されないファイル拡張子。
  • InvalidSpkiPinException — 不正な形式の TLS ピン文字列。
  • : GotenbergConvertException
  • トリガー: convertFile() または convertString() が、GotenbergConfig::isValid() が false の状態で呼び出されました。これは apiUrl が空文字列のときに発生します。
  • 修正: 空でない HTTPS URL を指定してください。設定を fromArray() で構築する場合、欠落または非文字列の api_url が黙って '' に置き換えられる点に注意してください。起動パスで設定ソースを検証してください。

これらはセキュリティポリシーに由来し、サーバーサイドリクエストフォージェリ(SSRF)を防ぎます。いずれもリクエストが送信されるに送出されます。素の RuntimeException です。

  • トリガー: 設定された URL スキームが https ではありません。このチェックは大文字小文字を区別しないため、HTTPS:// は受け入れられます。
  • 修正: Gotenberg の前段に TLS を配置し、HTTPS エンドポイントを設定してください。素の HTTP はローカル開発であっても拒否されます。
  • トリガー: URL をスキームとホストに解析できません。
  • 修正: 構文的に有効な絶対 URL を指定してください。たとえば https://gotenberg.example.com:3000 です。
  • トリガー: ホストがプライベートまたは予約済みの IP リテラルであるか、または(すべての A/AAAA レコードについて)プライベートもしくは予約済みのアドレスに解決されるホスト名です。このチェックは RFC 1918 の範囲、ループバック、リンクローカルアドレスをブロックします。
  • 修正: ルーティング可能なパブリックアドレス、または適切にセグメント化されたサービスアドレスにブリッジを向けてください。Gotenberg を意図的にプライベートネットワークに配置している場合、ブリッジの SSRF ガードは設計上それを拒否します。ガードが受け入れるアドレスを通じて公開し、そのパスをネットワーク制御と認証で保護してください。詳しくは /integrations/gotenberg/security-and-operations/. を参照してください。

“Gotenberg API URL DNS answer changed since validation — possible DNS rebinding attack”

「“Gotenberg API URL DNS answer changed since validation — possible DNS rebinding attack”」という見出しのセクション
  • トリガー: 初回の検証とリクエストの間に、新たな DNS 解決が、当初検証されたセットに含まれていなかったアドレスを返しました。
  • 修正: これは time-of-check/time-of-use ガードが作動したものです。そのホストの DNS を調査してください。正当な原因としては、アドレスをローテーションするロードバランサーが挙げられます。悪意ある原因はリバインディング攻撃です。Gotenberg エンドポイントには、安定したアドレス、または安定したレコードセットを持つ名前を使用してください。

これらはリクエストの前にセキュリティポリシーが送出します。特記しない限り、いずれも素の RuntimeException です。

  • : GotenbergConvertException
  • トリガー: convertFile() がパスを正規化できなかったか、解決後のパスが通常ファイルかつ読み取り可能なファイルではありません。ディレクトリを渡した場合も発生します。
  • 修正: 既存の読み取り可能なファイルへのパスを渡してください。パスはまず realpath() で正規化され、これによりトラバーサルも無効化されます。
  • トリガー: 入力が maxFileSize(デフォルト 52,428,800 バイト = 50 MiB)より大きいです。
  • 修正: ドキュメントが正当に必要とする場合は maxFileSize を引き上げるか、上流でアップロードを拒否してください。実際のドキュメントが許容する範囲で、上限はできるだけ低く保ってください。これはブリッジに唯一組み込まれているリソース境界です。

ファイル名は検査されます。ファイル変換では、ファイル名は解決後パスのベース名です。convertString() では渡した名前が使われます。いずれも RuntimeException です。

メッセージの断片トリガー
must not be empty空のファイル名
path traversal sequences (..)名前に .. が含まれている
forward slashes名前に / が含まれている
backslashes名前に \ が含まれている
null bytes名前に NUL バイトが含まれている
control characters名前に ASCII 制御文字(0〜31)が含まれている
  • 修正: クリーンなベース名を渡してください。convertString() には report.docx のような素の名前を指定してください。これはフォーマット検出とマルチパートアップロード時のファイル名に使われる値であり、パスとしては使用されません。
  • : ValueError
  • トリガー: ファイル拡張子が docxxlsxpptxodtodsodp のいずれでもありません(大文字小文字を区別せず、先頭のドットは許容されます)。
  • 修正: 認識される 6 つのフォーマットのみを変換対象にしてください。ブリッジはレガシーのバイナリフォーマット(.doc.xls.ppt)、.rtf.csv、プレーンテキスト、画像を認識しません。ブリッジを呼び出す前にこれらの入力を認識されるフォーマットに変換するか、別のパスで処理してください。

これらはすべて GotenbergConvertException です。

  • トリガー: PSR-18 クライアント(または cURL ピン留めトランスポート)がリクエスト送信中に例外をスローしました。原因は、接続拒否、タイムアウト、TLS ハンドシェイクの失敗、またはピンの不一致です。
  • 例外コード: 基盤となるクライアント例外のコード。
  • 原因: 元の PSR-18 クライアント例外が前段の例外(previous exception)として添付されます。
  • 修正: 次の 4 点を確認してください。isAvailable() でサービスへの到達性を確認してください。ネットワークパスを確認してください。TLS チェーンを確認してください。さらに、ピン留めが設定されている場合は、サーバーの現在の SubjectPublicKeyInfo(SPKI)が設定済みのピンのいずれかと一致することを確認してください。証明書ローテーション後のピン不一致が典型的な原因です。ローテーション手順は /integrations/gotenberg/security-and-operations/. を参照してください。
  • トリガー: cURL ピン留めトランスポートの curl_exec が非ゼロの cURL エラー番号で失敗したか、文字列以外のボディを返しました。
  • 修正: cURL エラー番号から原因を特定できます(TLS、解決、タイムアウト、ピン)。ピン留めの失敗は、CURLOPT_PINNEDPUBLICKEY が証明書を拒否したときにここで現れます。設定されたピンと解決されたアドレスが最新であることを確認してください。
  • トリガー: レスポンスのステータスが 200 ではありませんでした。ボディは含まれますが、先頭 500 文字に切り詰められ、それより長い場合は省略記号が付加されます。
  • 修正: 含まれているボディを読んでください。Gotenberg のエラーメッセージは、変換が拒否された理由(サポートされないドキュメント内容、LibreOffice の内部的な失敗、または 401403 での認証拒否)を説明します。401/403 は、apiKey が欠落しているか誤っていることを意味します。5xx はサービス側の失敗であり、上限付きリトライの候補です。
  • トリガー: ステータスは 200 でしたが、レスポンスの Content-Typeapplication/pdf が含まれていませんでした。
  • 修正: これは通常、プロキシまたはゲートウェイが HTML のエラーページやリダイレクトページを 200 で返したことを意味します。ブリッジはピン留めトランスポートでリダイレクト追従を意図的に無効化しているため、3xx が未検証のホストへ黙って追跡されることはありません。誤った型でボディが届くのは、クライアントと Gotenberg の間にある何かが干渉している兆候です。ネットワークパスを点検してください。
  • トリガー: ステータス 200Content-Type は許容範囲でしたが、ボディが %PDF シグネチャで始まっていません。
  • 修正: ヘッダーにもかかわらず、上流が PDF ではないものを返しました。レスポンスを信頼できないものとして扱い、サービスを調査してください。ボディをディスクに書き込まないでください。ブリッジはそれを結果として返すことを拒否します。
  • : InvalidSpkiPinException
  • トリガー: 設定されたピン文字列が sha256/ または sha256// で始まっていません。
  • 修正: 各ピンを sha256/<base64-encoded-spki-hash> の形式にしてください。トランスポートは cURL ネイティブの sha256//<base64> 形式も受け入れます。値は証明書全体からではなく、サーバー証明書の SubjectPublicKeyInfo から生成してください。

isAvailable() は、URL が空である、HTTPS でない、または private/reserved アドレスに解決される場合、ネットワーク呼び出しを一切行わずに false を返します。また、ネットワークエラーが発生したとき、または /health500 以上を返すときにも false を返します。これらの場合、例外をスローせずにエラーを捕捉します。次の順に確認してください。

  1. 設定された URL が空でなく HTTPS であること。
  2. ホストが private/reserved アドレスに解決されないこと(SSRF ガードはプローブに対しても拒否します)。
  3. <apiUrl>/health がアプリケーションホストから到達可能であり、500 未満のステータスを返すこと。
  • /integrations/gotenberg/configuration/ — すべてのオプションとトランスポート選択ルール。
  • /integrations/gotenberg/production-usage/ — リトライポリシーと失敗処理の契約。
  • /integrations/gotenberg/security-and-operations/ — SSRF モデルとピンローテーション。
  • /integrations/gotenberg/quickstart/ — 文脈込みの網羅的な catch 順序。