Solución de problemas
De un vistazo
Sección titulada «De un vistazo»El puente lanza tres tipos de excepción. La excepción capturada indica qué falló y si conviene reintentar o usar una alternativa. Cada fragmento de mensaje que aparece a continuación está tomado del código fuente.
La jerarquía de excepciones
Sección titulada «La jerarquía de excepciones»| Excepción | Extiende | Significado |
|---|---|---|
CloudflareNotAvailableException | NextPDF\Exception\NextPdfException | No se pudo alcanzar el edge o la configuración está incompleta, y no existe ninguna alternativa utilizable. |
CloudflareRenderException | NextPDF\Exception\NextPdfException | El Worker respondió, pero la representación falló (error HTTP o cuerpo mal formado). Nunca recurre a la alternativa. |
InvalidSpkiPinException | InvalidArgumentException | Una cadena de pin SPKI configurada está mal formada. |
CloudflareSecurityPolicy también lanza RuntimeException directamente ante infracciones de las políticas de entrada y de URL. Lo hace antes de enviar cualquier solicitud.
Fallos de configuración y de entrada
Sección titulada «Fallos de configuración y de entrada»| Fragmento de mensaje | Lanzado por | Causa | Solución |
|---|---|---|---|
incomplete (missing worker_url or api_token) | Renderizador (mediante la ruta alternativa) | workerUrl o apiToken vacío | Definir ambos; verificarlo con isValid(). |
HTML input exceeds maximum size | CloudflareSecurityPolicy::validate() | HTML más largo que maxHtmlSize | Reducir la entrada o aumentar maxHtmlSize deliberadamente. |
Base64 data URI exceeds safety limit | CloudflareSecurityPolicy::validate() | Un URI data:;base64, estimado en más de 13631488 bytes | Externalizar el recurso; no incrustar binarios grandes en línea. |
meta-refresh redirect which could cause SSRF | CloudflareSecurityPolicy::validate() | Una etiqueta <meta http-equiv="refresh"> | Eliminar la etiqueta; usar una redirección del lado del servidor fuera del HTML representado. |
Invalid Worker URL | validateWorkerUrl() | La URL no se puede analizar o carece de scheme/host | Proporcionar una URL HTTPS absoluta y completa. |
Worker URL must use HTTPS | validateWorkerUrl() | Esquema distinto de HTTPS | Usar https://. |
private or reserved IP addresses | validateWorkerUrl() | Literal de IP en el rango RFC 1918 / loopback / RFC 3927 | Apuntar a un endpoint público. |
hostname resolves to a private or reserved IP | validateWorkerUrl() | Un registro A/AAAA resuelto se clasifica como private/reserved | Corregir el DNS; investigar un posible rebinding. |
DNS answer changed since validation | assertPinsStillValid() | El host se resolvió a una nueva IP entre la comprobación y el envío | Volver a resolver; tratarlo como un posible intento de rebinding. |
Fallos del lado del Worker
Sección titulada «Fallos del lado del Worker»Son excepciones CloudflareRenderException. El Worker respondió, pero falló la representación en sí. No activan nunca la alternativa local: el edge estaba accesible.
| Fragmento de mensaje | Causa |
|---|---|
Cloudflare Worker returned HTTP <code>: <detail> | Estado diferente de 200. El detalle es el campo JSON error o los primeros 200 bytes del cuerpo. |
Worker returned empty or invalid PDF data | Respuesta binaria que no empieza por %PDF. |
Worker error: <message> | Respuesta JSON que incluye un campo error. |
JSON response missing "pdf" field | Respuesta JSON sin campo pdf. |
Invalid base64-encoded PDF in JSON response | El campo pdf no se descodificó desde base64 como bytes que empiezan por %PDF. |
Invalid JSON response from Worker | Content-Type: application/json pero el cuerpo no se descodificó como array. |
Unexpected Content-Type from Worker: <type> | Un 200 cuyo Content-Type no es ni application/pdf ni application/json. |
Si se captura uno de estos, conviene inspeccionar los registros del Worker. El fallo está del lado del Worker, no en este puente.
Fallos de accesibilidad y de alternativa
Sección titulada «Fallos de accesibilidad y de alternativa»Son excepciones CloudflareNotAvailableException. No se pudo usar el edge y ninguna alternativa produjo un PDF.
| Fragmento de mensaje | Causa | Solución |
|---|---|---|
Cloudflare Worker unavailable: <reason> | Error de transporte, alternativa deshabilitada | Habilitar fallbackToLocal y conectar una factoría, o corregir la conectividad. |
Artisan is installed but no LocalRendererFactoryInterface was provided | nextpdf/artisan presente, no se pasó ninguna factoría | Pasar un LocalRendererFactoryInterface al constructor. |
local Chrome fallback (nextpdf/artisan) is not installed | Alternativa habilitada, sin factoría, Artisan ausente | Ejecutar composer require nextpdf/artisan y conectar una factoría. |
Cuando se proporciona un logger PSR-3 y se ejecuta la ruta alternativa, el puente registra un warning (Cloudflare render failed, attempting fallback) y luego un info (Falling back to local renderer).
Fallos de transporte / pinning
Sección titulada «Fallos de transporte / pinning»| Síntoma | Causa | Solución |
|---|---|---|
InvalidSpkiPinException: Invalid SPKI pin format | Un pin que no tiene la forma sha256/<base64> (ni sha256//<base64>) | Corregir la cadena del pin. |
cURL transport error (<n>): <msg> | Fallo a nivel de cURL (TLS, DNS, tiempo de espera) | Inspeccionar el número de error de cURL; si hay pins definidos, confirmar que el SPKI servido sigue estando fijado. |
| Las representaciones fallan inmediatamente tras la rotación del certificado | El SPKI del nuevo certificado no está incluido en el conjunto de pins | Añadir el nuevo SPKI como pin de respaldo antes de rotar. |
| No se usa el transporte fijado pese a que hay pins configurados | No se proporcionó ningún ResponseFactory PSR-17 | Pasar un ResponseFactory; el transporte fijado lo requiere. |
Comportamiento de isAvailable()
Sección titulada «Comportamiento de isAvailable()»isAvailable() no lanza nunca una excepción. Devuelve false cuando la configuración no es válida o cuando el sondeo HEAD falla o lanza una excepción. Solo devuelve true cuando el sondeo responde con un estado inferior a 500. Un resultado true es solo un indicio: el POST posterior aún puede fallar con cualquiera de los errores del lado del Worker anteriores. No considerar un sondeo exitoso como garantía.
Sorpresas del límite de tasa
Sección titulada «Sorpresas del límite de tasa»El limitador ApiProtection mantiene estado en memoria por proceso. Los contadores no sobreviven a un reinicio y no se comparten entre workers ni nodos. Por tanto, si se observa que un cliente queda permitido en un nodo y denegado en otro, es el comportamiento esperado. Anteponer al limitador un almacén compartido para aplicar un límite a escala de clúster.
Véase también
Sección titulada «Véase también»- /integrations/cloudflare/security-and-operations/ — el manual operativo y los controles que hay detrás de estos mensajes.
- /integrations/cloudflare/quickstart/ — la forma canónica de usar try/catch.
- /integrations/cloudflare/production-usage/ — detalles para conectar la alternativa.