Ir al contenido

Solución de problemas de Artisan

Cada fallo del puente se manifiesta como una excepción tipada. Asociar la excepción y el mensaje con la tabla siguiente. Cada fila apunta a la comprobación de origen exacta, para corregir la causa y no el síntoma.

chrome-php/chrome is not installed. Install it via: composer require chrome-php/chrome:^1.15

La biblioteca cliente CDP no está en el autoloader. BrowserPool::getBrowser() la lanza antes de cualquier arranque de Chrome. Ejecutar el comando de instalación. Esto se distingue de un binario ausente: la comprobación de la biblioteca y la comprobación del binario son etapas separadas.

ChromeRenderException — arranque o tiempo de espera agotado

Sección titulada «ChromeRenderException — arranque o tiempo de espera agotado»

Chrome renderer failed: <cause>

Chrome no pudo iniciarse, agotó el tiempo de espera o se cerró inesperadamente. La excepción previa contiene la causa original. Causas comunes:

  • Binario no encontrado / no ejecutable. Verificarlo con chromium --headless --dump-dom about:blank. Establecer chrome_binary con la ruta absoluta.
  • El sandbox no puede inicializarse (contenedores). La causa menciona el sandbox o el namespace. Aprovisionar un contenedor con sandbox habilitado (preferido), o establecer no_sandbox: true después de leer /integrations/artisan/security-and-operations/.
  • Tiempo de espera agotado. Un documento pesado superó render_timeout. Aumentar el tiempo de espera para esa carga de trabajo o reducir el documento; valorar el equilibrio frente a la denegación de servicio en una ruta expuesta al usuario.
  • Faltan bibliotecas compartidas. Chrome se cierra de inmediato. Instalar el conjunto de dependencias de Chrome de la distribución.

Chrome printToPDF returned empty data

Chrome se inició y printToPDF devolvió cero bytes. La causa habitual es una entrada que no produce ninguna caja renderizada (cuerpo vacío, todo el contenido en display:none), o un cierre inesperado de Chrome a mitad de impresión. Confirmar que el HTML se renderice en una caja visible. Revisar la presión de memoria del host.

RuntimeException — entrada rechazada antes de Chrome

Sección titulada «RuntimeException — entrada rechazada antes de Chrome»
El mensaje contieneCausaSolución
exceeds maximum allowed sizeHTML que supera maxHtmlSizeReducir la entrada o aumentar max_html_size (amplía la superficie de agotamiento de recursos)
oversized base64 data URIbase64 en línea ≥ 13 MBReducir el recurso incrustado; referenciar una imagen más pequeña
forbidden meta refresh redirect<meta http-equiv="refresh"> presenteEliminar la etiqueta; es un vector de navegación SSRF y siempre se rechaza

Estas provienen de ChromeSecurityPolicy::validate() y se activan antes de contactar con Chrome, por lo que son rápidas y de bajo coste de cubrir en las pruebas.

Page <n> has no content stream

Chrome produjo un PDF del que el analizador no pudo extraer ninguna página. Esto es poco frecuente y apunta a una salida malformada de Chrome o a una versión de Chrome que produce una estructura inesperada. Capturar la versión de Chrome y la entrada. Verificar que el binario sea una compilación de Chrome/Chromium compatible.

Los recursos remotos se renderizan en blanco

Sección titulada «Los recursos remotos se renderizan en blanco»

Esto no es un error. El puente bloquea toda descarga de subrecursos (la CSP default-src 'none' y un bloqueo CDP setBlockedURLs('*')). Las <img> remotas, las hojas de estilo, las fuentes, los scripts y los iframes no se cargan. Incrustar los recursos como URI data:, e incrustar el CSS mediante defaultCss o <style>. Consultar el modelo de red en /integrations/artisan/security-and-operations/.

El contenido se recorta en la parte inferior

Sección titulada «El contenido se recorta en la parte inferior»

El documento se desbordó a una segunda página de Chrome y el puente importó solo la página 0. O bien el búfer de ajuste automático fue demasiado pequeño para un reflujo inusualmente alto, o la altura explícita era demasiado pequeña. Proporcionar una altura explícita dimensionada al contenido, o quitar la altura explícita para usar el ajuste automático con su búfer de seguridad. Consultar el manejo de la altura en /integrations/artisan/production-usage/.

Esto es lo esperado. BrowserPool reinicia Chrome cada 100 renderizados para acotar la memoria. Una línea de registro de nivel notice registra el reinicio con el recuento de renderizados. Tratarlo como un costo periódico conocido en los SLO, no como un incidente. Una tasa de reinicio superior a una vez cada 100 renderizados significa que los documentos son más pesados de lo esperado.

BrowserPool acota el crecimiento con el reinicio cada 100 renderizados, pero un worker de vida muy larga aún puede acumular memoria. Llamar a close() entre lotes grandes para reciclar el proceso de Chrome de forma temprana, y ejecutar el worker con un límite de memoria del host.

  1. Reproducir el problema con un fragmento HTML de confianza mínimo para aislar la entrada del entorno.
  2. Ejecutar chromium --headless --dump-dom about:blank en el host como el usuario del worker.
  3. Inyectar un logger PSR-3 y leer las líneas info/notice (ruta del binario, recuento de reinicios).
  4. Confirmar que chrome-php/chrome esté instalado: lo está si BrowserPool::getBrowser() no lanza ChromeNotAvailableException.
  5. Revisar la excepción previa de la excepción para conocer la causa subyacente de Chrome.
  • /integrations/artisan/install/
  • /integrations/artisan/configuration/
  • /integrations/artisan/security-and-operations/
  • /integrations/artisan/chrome-renderer-setup/
  • /integrations/artisan/production-usage/