NextPDF Gotenberg のトラブルシューティング
ブリッジは明確かつ早期に失敗します。いずれの失敗も型付き例外であり、メッセージで原因が分かるようになっています。このページは、それらを一覧化したカタログです。各失敗について、例外の型、表示されるメッセージの断片、コードパス上の正確なトリガー、修正方法を示します。
例外のファミリーは次のとおりです。
GotenbergConvertException— 変換レイヤーの失敗(設定、トランスポート、またはレスポンス)。RuntimeException— ネットワーク通信が発生する前に、セキュリティポリシーが送出する検証レイヤーの失敗。ValueError— 認識されないファイル拡張子。InvalidSpkiPinException— 不正な形式の TLS ピン文字列。
設定の失敗
「設定の失敗」という見出しのセクション”Invalid Gotenberg configuration: apiUrl is empty”
「”Invalid Gotenberg configuration: apiUrl is empty”」という見出しのセクション- 型:
GotenbergConvertException - トリガー:
convertFile()またはconvertString()が、GotenbergConfig::isValid()が false の状態で呼び出されました。これはapiUrlが空文字列のときに発生します。 - 修正: 空でない HTTPS URL を指定してください。設定を
fromArray()で構築する場合、欠落または非文字列のapi_urlが黙って''に置き換えられる点に注意してください。起動パスで設定ソースを検証してください。
URL とアドレス(SSRF)の失敗
「URL とアドレス(SSRF)の失敗」という見出しのセクションこれらはセキュリティポリシーに由来し、サーバーサイドリクエストフォージェリ(SSRF)を防ぎます。いずれもリクエストが送信される前に送出されます。素の RuntimeException です。
“Gotenberg API URL must use HTTPS (got: http)”
「“Gotenberg API URL must use HTTPS (got: http)”」という見出しのセクション- トリガー: 設定された URL スキームが
httpsではありません。このチェックは大文字小文字を区別しないため、HTTPS://は受け入れられます。 - 修正: Gotenberg の前段に TLS を配置し、HTTPS エンドポイントを設定してください。素の HTTP はローカル開発であっても拒否されます。
“Invalid Gotenberg API URL: unable to parse”
「“Invalid Gotenberg API URL: unable to parse”」という見出しのセクション- トリガー: URL をスキームとホストに解析できません。
- 修正: 構文的に有効な絶対 URL を指定してください。たとえば
https://gotenberg.example.com:3000です。
“Gotenberg API URL must not resolve to a private or reserved IP address”
「“Gotenberg API URL must not resolve to a private or reserved IP address”」という見出しのセクション- トリガー: ホストがプライベートまたは予約済みの 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 です。
“File not found or not readable: ”
「“File not found or not readable: ”」という見出しのセクション- 型:
GotenbergConvertException - トリガー:
convertFile()がパスを正規化できなかったか、解決後のパスが通常ファイルかつ読み取り可能なファイルではありません。ディレクトリを渡した場合も発生します。 - 修正: 既存の読み取り可能なファイルへのパスを渡してください。パスはまず
realpath()で正規化され、これによりトラバーサルも無効化されます。
“File size ( bytes) exceeds maximum allowed size ( bytes)”
「“File size ( bytes) exceeds maximum allowed size ( bytes)”」という見出しのセクション- トリガー: 入力が
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のような素の名前を指定してください。これはフォーマット検出とマルチパートアップロード時のファイル名に使われる値であり、パスとしては使用されません。
“Unknown office format extension: ”
「“Unknown office format extension: ”」という見出しのセクション- 型:
ValueError - トリガー: ファイル拡張子が
docx、xlsx、pptx、odt、ods、odpのいずれでもありません(大文字小文字を区別せず、先頭のドットは許容されます)。 - 修正: 認識される 6 つのフォーマットのみを変換対象にしてください。ブリッジはレガシーのバイナリフォーマット(
.doc、.xls、.ppt)、.rtf、.csv、プレーンテキスト、画像を認識しません。ブリッジを呼び出す前にこれらの入力を認識されるフォーマットに変換するか、別のパスで処理してください。
トランスポートとレスポンスの失敗
「トランスポートとレスポンスの失敗」という見出しのセクションこれらはすべて GotenbergConvertException です。
“Gotenberg HTTP request failed: ”
「“Gotenberg HTTP request failed: ”」という見出しのセクション- トリガー: PSR-18 クライアント(または cURL ピン留めトランスポート)がリクエスト送信中に例外をスローしました。原因は、接続拒否、タイムアウト、TLS ハンドシェイクの失敗、またはピンの不一致です。
- 例外コード: 基盤となるクライアント例外のコード。
- 原因: 元の PSR-18 クライアント例外が前段の例外(previous exception)として添付されます。
- 修正: 次の 4 点を確認してください。
isAvailable()でサービスへの到達性を確認してください。ネットワークパスを確認してください。TLS チェーンを確認してください。さらに、ピン留めが設定されている場合は、サーバーの現在の SubjectPublicKeyInfo(SPKI)が設定済みのピンのいずれかと一致することを確認してください。証明書ローテーション後のピン不一致が典型的な原因です。ローテーション手順は /integrations/gotenberg/security-and-operations/. を参照してください。
“cURL transport error (): ”
「“cURL transport error (): ”」という見出しのセクション- トリガー: cURL ピン留めトランスポートの
curl_execが非ゼロの cURL エラー番号で失敗したか、文字列以外のボディを返しました。 - 修正: cURL エラー番号から原因を特定できます(TLS、解決、タイムアウト、ピン)。ピン留めの失敗は、
CURLOPT_PINNEDPUBLICKEYが証明書を拒否したときにここで現れます。設定されたピンと解決されたアドレスが最新であることを確認してください。
“Gotenberg conversion failed with HTTP : ”
「“Gotenberg conversion failed with HTTP : ”」という見出しのセクション- トリガー: レスポンスのステータスが
200ではありませんでした。ボディは含まれますが、先頭 500 文字に切り詰められ、それより長い場合は省略記号が付加されます。 - 修正: 含まれているボディを読んでください。Gotenberg のエラーメッセージは、変換が拒否された理由(サポートされないドキュメント内容、LibreOffice の内部的な失敗、または
401や403での認証拒否)を説明します。401/403は、apiKeyが欠落しているか誤っていることを意味します。5xxはサービス側の失敗であり、上限付きリトライの候補です。
“Unexpected Content-Type from Gotenberg: (expected application/pdf)”
「“Unexpected Content-Type from Gotenberg: (expected application/pdf)”」という見出しのセクション- トリガー: ステータスは
200でしたが、レスポンスのContent-Typeにapplication/pdfが含まれていませんでした。 - 修正: これは通常、プロキシまたはゲートウェイが HTML のエラーページやリダイレクトページを
200で返したことを意味します。ブリッジはピン留めトランスポートでリダイレクト追従を意図的に無効化しているため、3xxが未検証のホストへ黙って追跡されることはありません。誤った型でボディが届くのは、クライアントと Gotenberg の間にある何かが干渉している兆候です。ネットワークパスを点検してください。
“Response body does not start with %PDF header — invalid PDF data”
「“Response body does not start with %PDF header — invalid PDF data”」という見出しのセクション- トリガー: ステータス
200、Content-Typeは許容範囲でしたが、ボディが%PDFシグネチャで始まっていません。 - 修正: ヘッダーにもかかわらず、上流が PDF ではないものを返しました。レスポンスを信頼できないものとして扱い、サービスを調査してください。ボディをディスクに書き込まないでください。ブリッジはそれを結果として返すことを拒否します。
ピン設定の失敗
「ピン設定の失敗」という見出しのセクション”Invalid SPKI pin format: (expected sha256/)”
「”Invalid SPKI pin format: (expected sha256/)”」という見出しのセクション- 型:
InvalidSpkiPinException - トリガー: 設定されたピン文字列が
sha256/またはsha256//で始まっていません。 - 修正: 各ピンを
sha256/<base64-encoded-spki-hash>の形式にしてください。トランスポートは cURL ネイティブのsha256//<base64>形式も受け入れます。値は証明書全体からではなく、サーバー証明書の SubjectPublicKeyInfo から生成してください。
“It says unavailable but the service is up”
「“It says unavailable but the service is up”」という見出しのセクションisAvailable() は、URL が空である、HTTPS でない、または private/reserved アドレスに解決される場合、ネットワーク呼び出しを一切行わずに false を返します。また、ネットワークエラーが発生したとき、または /health が 500 以上を返すときにも false を返します。これらの場合、例外をスローせずにエラーを捕捉します。次の順に確認してください。
- 設定された URL が空でなく HTTPS であること。
- ホストが private/reserved アドレスに解決されないこと(SSRF ガードはプローブに対しても拒否します)。
<apiUrl>/healthがアプリケーションホストから到達可能であり、500未満のステータスを返すこと。
- /integrations/gotenberg/configuration/ — すべてのオプションとトランスポート選択ルール。
- /integrations/gotenberg/production-usage/ — リトライポリシーと失敗処理の契約。
- /integrations/gotenberg/security-and-operations/ — SSRF モデルとピンローテーション。
- /integrations/gotenberg/quickstart/ — 文脈込みの網羅的な catch 順序。