NextPDF Gotenberg troubleshooting
At a glance
Section titled “At a glance”The bridge fails loudly and early. Every failure raises a typed exception with a message that names the cause. Use this page as the catalog. For each failure, you get the exception type, the message fragment you will see, the exact trigger in the code path, and the fix.
The exception families are:
GotenbergConvertException— a conversion-layer failure (config, transport, or response).RuntimeException— a validation-layer failure raised by the security policy before any network traffic.ValueError— an unrecognized file extension.InvalidSpkiPinException— a malformed Transport Layer Security (TLS) SubjectPublicKeyInfo (SPKI) pin string.
Configuration failures
Section titled “Configuration failures””Invalid Gotenberg configuration: apiUrl is empty”
Section titled “”Invalid Gotenberg configuration: apiUrl is empty””- Type:
GotenbergConvertException - Trigger: You called
convertFile()orconvertString()whileGotenbergConfig::isValid()is false. This happens whenapiUrlis an empty string. - Fix: Supply a non-empty HTTPS URL. If you build the config with
fromArray(), note that it silently substitutes''for a missing or non-stringapi_url. Validate your config source during boot.
URL and address (SSRF) failures
Section titled “URL and address (SSRF) failures”These failures come from the security policy, which guards against
server-side request forgery (SSRF). The bridge raises them before it
sends any request. Each one is a plain RuntimeException.
”Gotenberg API URL must use HTTPS (got: http)”
Section titled “”Gotenberg API URL must use HTTPS (got: http)””- Trigger: The configured URL scheme is not
https. The check is case-insensitive, soHTTPS://is accepted. - Fix: Put Gotenberg behind TLS and configure the HTTPS endpoint. Plain HTTP is rejected even for local development.
”Invalid Gotenberg API URL: unable to parse”
Section titled “”Invalid Gotenberg API URL: unable to parse””- Trigger: The URL cannot be parsed into a scheme and host.
- Fix: Provide a syntactically valid absolute URL, for example
https://gotenberg.example.com:3000.
”Gotenberg API URL must not resolve to a private or reserved IP address”
Section titled “”Gotenberg API URL must not resolve to a private or reserved IP address””- Trigger: The host is a private or reserved Internet Protocol (IP) literal, or a hostname that resolves (via all A/AAAA records) to any private or reserved address. This blocks the private ranges from Request for Comments (RFC) 1918, loopback, and link-local addresses.
- Fix: Point the bridge at a routable public address or a properly segmented service address. If your Gotenberg is intentionally on a private network, the bridge’s SSRF guard rejects it by design. Expose it through an address the guard accepts, then protect that path with network controls and authentication. See /integrations/gotenberg/security-and-operations/.
”Gotenberg API URL DNS answer changed since validation — possible DNS rebinding attack”
Section titled “”Gotenberg API URL DNS answer changed since validation — possible DNS rebinding attack””- Trigger: Between initial validation and the request, a fresh Domain Name System (DNS) resolution returned an address that was not in the originally validated set.
- Fix: This is the time-of-check/time-of-use guard firing. Investigate DNS for the host. A valid cause is a load balancer rotating addresses. A malicious cause is a rebinding attack. Use a stable address or a name with a stable record set for the Gotenberg endpoint.
Input validation failures
Section titled “Input validation failures”The security policy raises these failures before the request. Each one is
a plain RuntimeException unless noted.
”File not found or not readable: ”
Section titled “”File not found or not readable: ””- Type:
GotenbergConvertException - Trigger:
convertFile()could not canonicalize the path, or the resolved path is not a regular readable file. A directory triggers this too. - Fix: Pass a path to an existing, readable file. The path is
canonicalized with
realpath()first, which also defeats traversal.
”File size ( bytes) exceeds maximum allowed size ( bytes)”
Section titled “”File size ( bytes) exceeds maximum allowed size ( bytes)””- Trigger: The input is larger than
maxFileSize(default 52,428,800 bytes = 50 MiB). - Fix: Raise
maxFileSizeif the document legitimately needs it, or reject the upload upstream. Keep the cap as low as your real documents allow. It is the bridge’s only built-in resource limit.
Filename rejections
Section titled “Filename rejections”The bridge validates the filename. For file conversions, the filename is
the basename of the resolved path; for convertString(), it is the name
you pass in. Each of these is a RuntimeException:
| Message fragment | Trigger |
|---|---|
must not be empty | empty filename |
path traversal sequences (..) | the name contains .. |
forward slashes | the name contains / |
backslashes | the name contains \ |
null bytes | the name contains a NUL byte |
control characters | the name contains an ASCII control character (0–31) |
- Fix: Pass a clean basename. For
convertString(), supply a plain name such asreport.docx. It is used for format detection and as the multipart upload filename, not as a path.
”Unknown office format extension: ”
Section titled “”Unknown office format extension: ””- Type:
ValueError - Trigger: The file extension is not one of
docx,xlsx,pptx,odt,ods,odp(case-insensitive, leading dot tolerated). - Fix: Convert only the six recognized formats. The bridge does not
recognize the legacy binary formats (
.doc,.xls,.ppt),.rtf,.csv, plain text, or images. Convert these inputs to a recognized format before you call the bridge, or route them through a different path.
Transport and response failures
Section titled “Transport and response failures”All of these are GotenbergConvertException.
”Gotenberg HTTP request failed: ”
Section titled “”Gotenberg HTTP request failed: ””- Trigger: The PHP Standard Recommendation 18 (PSR-18) client (or the cURL-pinned transport) raised an exception while sending the request. The cause is connection refusal, a timeout, a TLS handshake failure, or a pin mismatch.
- Exception code: the underlying client exception’s code.
- Cause: the original PSR-18 client exception is attached as the previous exception.
- Fix: Check four things. Check service reachability with
isAvailable(). Check the network path. Check the TLS chain. If pinning is configured, check that the server’s current SubjectPublicKeyInfo (SPKI) matches a configured pin. A pin mismatch after a certificate rotation is the classic cause. See the rotation procedure in /integrations/gotenberg/security-and-operations/.
“cURL transport error (): ”
Section titled ““cURL transport error (): ””- Trigger: The cURL-pinned transport’s
curl_execfailed with a non-zero cURL error number, or returned a non-string body. - Fix: The cURL error number identifies the cause (TLS, resolve,
timeout, pin). A pinning failure surfaces here when
CURLOPT_PINNEDPUBLICKEYrejects the certificate. Confirm that the configured pins and the resolved address are current.
”Gotenberg conversion failed with HTTP : ”
Section titled “”Gotenberg conversion failed with HTTP : ””- Trigger: The response status was not
200. The body is included, truncated to the first 500 characters, with an ellipsis appended when longer. - Fix: Read the included body. Gotenberg’s error message explains
why the conversion was rejected: unsupported document content, an
internal LibreOffice failure, or an authentication rejection on a
401or403. A401/403means theapiKeyis missing or wrong. A5xxis a service-side failure and is the candidate for a bounded retry.
”Unexpected Content-Type from Gotenberg: (expected application/pdf)”
Section titled “”Unexpected Content-Type from Gotenberg: (expected application/pdf)””- Trigger: The status was
200, but the responseContent-Typedid not containapplication/pdf. - Fix: This usually means a proxy or gateway returned an HTML error
or redirect page with a
200. The bridge disables redirect following on the pinned transport deliberately, so a3xxresponse is not silently followed to an unvetted host. A body arriving with the wrongContent-Typesignals that something between you and Gotenberg is interfering. Inspect the network path.
”Response body does not start with %PDF header — invalid PDF data”
Section titled “”Response body does not start with %PDF header — invalid PDF data””- Trigger: Status
200,Content-Typeacceptable, but the body does not begin with the%PDFsignature. - Fix: The upstream returned something that is not a Portable Document Format (PDF) file despite the headers. Treat the response as untrusted and investigate the service. Do not write the body to disk. The bridge refuses to return it as a result.
Pin configuration failures
Section titled “Pin configuration failures””Invalid SPKI pin format: (expected sha256/)”
Section titled “”Invalid SPKI pin format: (expected sha256/)””- Type:
InvalidSpkiPinException - Trigger: A configured pin string does not start with
sha256/orsha256//. - Fix: Format each pin as
sha256/<base64-encoded-spki-hash>. The transport also accepts the cURL-nativesha256//<base64>form. Generate the value from the server certificate’s SubjectPublicKeyInfo, not from the whole certificate.
”It says unavailable but the service is up”
Section titled “”It says unavailable but the service is up””isAvailable() returns false without any network call when the URL is
empty, not HTTPS, or resolves to a private/reserved address. It also
returns false on any network error, or when /health returns 500 or
above; in those cases, it catches the error instead of throwing. Check,
in order:
- The configured URL is non-empty and HTTPS.
- The host does not resolve to a private/reserved address (the SSRF guard rejects it even for the probe).
<apiUrl>/healthis reachable from the application host and returns a status below500.
See also
Section titled “See also”- /integrations/gotenberg/configuration/ — all options and transport-selection rules.
- /integrations/gotenberg/production-usage/ — retry policy and the failure-handling contract.
- /integrations/gotenberg/security-and-operations/ — the SSRF model and pin rotation.
- /integrations/gotenberg/quickstart/ — the exhaustive catch order in context.