コンテンツにスキップ

NextPDF Laravel パッケージのトラブルシューティング

このページでは、パッケージで観測される各障害モードを、ソースで検証済みの根本原因に対応付けます。各項目には、症状、原因、対処方法を記載しています。

Terminal window
composer require nextpdf/laravel
php artisan vendor:publish --tag=nextpdf-config

報告される問題のほとんどは、ディスカバリー、コンテナの resolve(解決)、署名、キュージョブ、HTTP ファイル名という 5 つのグループに分類されます。このパッケージは、設計上、エラーを明示的に発生させます。未構成のオプション機能は null を返し、安全でない入力は型付きの例外を発生させます。そのため、多くの場合は症状から原因を直接特定できます。

症状検証済みの原因対処方法
インストール後にプロバイダーが登録されないアプリケーション側でオプトアウトに使用された設定 extra.laravel.dont-discover設定 dont-discover からのパッケージ削除、またはクラス NextPdfServiceProvider のファイル bootstrap/providers.php への手動登録
config('nextpdf') が空である公開されているバインディングがまだ解決されておらず、設定がマージされていない状態(遅延プロバイダー)provides() のいずれかのエントリーの解決、またはディスカバリー確認コマンド php artisan package:discover --ansi
config/nextpdf.php が publish で作成されないpublish タグの不一致正確なタグを使用します: php artisan vendor:publish --tag=nextpdf-config
RuntimeException: “NextPDF requires the ext-mbstring/ext-zlib PHP extension”(必須の PHP 拡張機能が不足)実行時に必須の PHP 拡張機能が見つからない拡張機能 mbstring および zlib のインストールまたは有効化、ファイル php.ini の設定
症状検証済みの原因対処方法
app(SignerInterface::class)null を返すnextpdf.signature で署名が無効、または証明書が空であるsignature.enabled = true と有効な signature.certificate を設定します。署名の具象実装には nextpdf/premium をインストールします
app(TsaClient::class) の戻り値が nullnextpdf.tsa.url が空である設定対象 tsa.url(必要に応じて credentials/pins も設定)
PDF/A バージョン型でクラスが見つからないnextpdf.pdfa が null 以外だが、nextpdf/premium がインストールされていないnextpdf/premium のインストール、または設定 pdfanull への復帰
e-invoice コントラクトの解決時にクラスが見つからないバインディングは登録されているが、Premium の具象実装が存在しないnextpdf/premium のインストール。e-invoice コントラクトは遅延解決され、Premium がない場合は最初の解決時にのみエラーになります
2 つの論理操作にまたがって同じドキュメントが変更されるドキュメントのバインディングはファクトリーである一方、解決済みのインスタンスを 1 つ再利用しているドキュメントごとの新しい PdfDocumentInterface の解決

該当エントリーのないコンテナは、get() で not-found 例外をスローします(PSR-11 §1.1.2)。e-invoice コントラクトは バインド済み であるため、コンテナの has() は true になります。このエラーは、コンテナ自体からではなく、構築時に不足している Premium の具象実装から発生します。

症状検証済みの原因対処方法
InvalidArgumentException: Path traversal sequences are not allowed出力パスに .. セグメントが含まれているストレージディレクトリ配下の、トラバーサルを含まない絶対パスの使用
InvalidArgumentException: Stream wrappers are not allowedパスが php:// のようなスキームに一致している通常のファイルシステムパスの使用
InvalidArgumentException: Output path contains null bytesパスに \0 バイトが含まれているディスパッチ前のパスのサニタイズ
InvalidArgumentException: Output path must end with .pdf extensionパスが .pdf で終わっていない(大文字小文字を区別しない)サフィックス .pdf(または .PDF)の使用
ジョブは実行されるが、ファイルが空または不正であるビルダークロージャが、構成済みのドキュメントを返さなかったビルダーからドキュメントを返します。返された値が保存されます
ジョブが誤ったキューまたはタイムアウトを使用しているnextpdf.queue.* が想定どおりに設定されていない設定対象のキー queue.queuequeue.connectionqueue.timeout。サブクラス化が必要なキーは triesbackoff

パスのチェックはワーカー上の handle() 内で実行されるため、不正なパスはディスパッチ時ではなく実行時に失敗します。これは意図的なものです。キュートランスポート上でシリアライズされたペイロードは、実際に消費される場所で検証されます。

症状検証済みの原因対処方法
ダウンロードのファイル名が、意図せず document.pdf になる空のファイル名が渡されたため、ファクトリーが既定値を設定している空でないファイル名の指定
ファイル名からパスや特殊文字が失われたファイル名のサニタイザーが、パス区切り文字、制御文字、null バイトを除去するベースのファイル名のみを渡します。これは想定どおりのハードニングです
非 ASCII のファイル名が、一部のクライアントで文字化けする非 ASCII の名前に対しては RFC 5987 の filename*= が出力されますが、古いクライアントは ASCII のフォールバックを読み取ります想定どおりの動作です。レガシークライアントで完全に一致させる必要がある場合は、ASCII セーフな名前を指定します
ストリーミングレスポンスでヘッダー Content-Length が欠けているストリーミングレスポンスは、設計上 Content-Length を省略します(チャンク出力)想定どおりの動作です。length ヘッダーが必要な場合は、非ストリーミングの inline()/download() を使用します
Terminal window
# Confirm the provider is discovered
php artisan package:discover --ansi
# Inspect merged configuration
php artisan tinker --execute="dump(config('nextpdf.queue'));"
resource: src/Laravel/NextPdfServiceProvider.php (null-check pattern)
<?php
declare(strict_types=1);
use NextPDF\Contracts\SignerInterface;
$signer = app(SignerInterface::class);
if ($signer === null) {
// Signing not configured, or nextpdf/premium not installed.
// Continue without a signature, or fail with a clear message.
}
  • 遅延プロバイダーであるため、新規インストール直後は、対象エントリーの初回解決が行われるまで「壊れている」ように見えることがあります。正しい成功サインは、package:discover にパッケージが一覧表示されることです。
  • image_cache_mb = null は 50 MB にフォールバックします。キャッシュを無効化できるのは 0 のみです。 「キャッシュが無効化されない」という報告では、通常 null が使われていました。
  • signature.level = null は、暗黙的に PAdES B-B にフォールバックします。「想定外の B-B」という報告では、通常 level が未設定のままになっていました。

長時間稼働するワーカーで最初のリクエストが遅い場合、フォントレジストリがオンデマンドで解析を行っています。nextpdf.preload_fonts を設定し、ウォームアップがワーカーのブート時に一度だけ実行されるようにします。詳細については、/integrations/laravel/configuration/ と /integrations/laravel/boot-and-discovery/ を参照してください。

パスとファイル名の拒否は、バグではなくセキュリティ対策です。事前にデコードしたり、チェックを緩めたりして回避しないでください。代わりに、管理されたストレージパスを経由してファイルを出力してください。/integrations/laravel/security-and-operations/. を参照してください。

主張ソース条項リファレンス ID
コンテナエントリーが欠落している場合、get() で not-found をスローするPSR-11 コンテナ§1.1.2
  • /integrations/laravel/install/ — ディスカバリーと publish の手順
  • /integrations/laravel/configuration/ — すべてのキーとその既定値
  • /integrations/laravel/production-usage/ — DI とキューのパターン
  • /integrations/laravel/security-and-operations/ — パスチェックが存在する理由