Ir al contenido
getnextpdf.com

Errores de tiempo de ejecución y de soporte

Estas entradas documentan las excepciones que lanza la capa de soporte de tiempo de ejecución: la política de degradación, el transporte HTTP respaldado por cURL, el disyuntor de resiliencia, el emisor de Gestión de Información y Eventos de Seguridad (SIEM), el manifiesto de representación, la inspección de PDF y el subsistema de ingeniería del caos.

Toda excepción de NextPDF extiende NextPdfException, que implementa ContextAwareExceptionInterface y expone getContext(): array para el registro de diagnóstico estructurado. Una subclase rellena ese arreglo solo cuando redefine getContext(); la base devuelve un arreglo vacío. Tres excepciones de esta página (DegradedException, CircuitBreakerOpenException e InspectException) extienden directamente RuntimeException de PHP y exponen sus datos a través de propiedades públicas de readonly en lugar de getContext(). Cada entrada de abajo nombra las propiedades exactas o las claves de contexto que transporta la clase, tomadas del código fuente.

  • Se lanza cuando. La canalización de representación encuentra una capacidad degradada que viola la política de degradación activa. Bajo DegradationPolicy::Strict, cualquier degradación de alto impacto (ComplianceRisk, SemanticLoss o Blocking) la lanza; bajo DegradationPolicy::Balanced, solo un impacto Blocking la lanza.
  • Clase. Extiende directamente RuntimeException (no NextPdfException), de modo que no transporta getContext().
  • Datos transportados. Dos propiedades públicas de readonly: $capability (el objeto de valor Capability que desencadenó el rechazo, incluidos su id, status, reason, fallbackTarget e impact) y $policy (la DegradationPolicy activa en el momento del rechazo). El mensaje tiene la forma Feature "<id>" is <status>: <reason> (policy: <policy>).
  • Recuperación. Inspeccionar $capability para identificar la funcionalidad ausente y su causa. Bien instalar el componente que la capacidad requiere, bien aceptar una configuración de menor impacto, o bien relajar la política de Strict a Balanced cuando la degradación es aceptable para el caso de uso. Llamar a $capability->isAvailable() / isDegraded() para impulsar los mensajes de cara al usuario.

Estas tres excepciones se originan en el cliente PSR-18 respaldado por cURL y en su decorador consciente de la seguridad. Las dos primeras extienden NextPdfException pero no redefinen getContext(), de modo que su getContext() devuelve un arreglo vacío; los datos de diagnóstico se alcanzan a través del captador getRequest() de PSR-18 y de la lanzable previa encadenada.

  • Se lanza cuando. La solicitud HTTP no puede completarse a causa de un fallo a nivel de red: fallo de resolución del Sistema de Nombres de Dominio (DNS), tiempo de espera de conexión o error de protocolo de enlace de la Seguridad de la Capa de Transporte (TLS). Es también la clase que el decorador consciente de la seguridad lanza ante un rechazo de seguridad (rechazo de Falsificación de Solicitud del Lado del Servidor, rechazo de reenlace de DNS o una redirección denegada).
  • Clase. Implementa Psr\Http\Client\NetworkExceptionInterface de PSR-18.
  • Datos transportados. getRequest() devuelve el RequestInterface fallido. El error de transporte de origen, cuando está presente, es la lanzable previa encadenada. getContext() devuelve un arreglo vacío (el valor predeterminado de la base).
  • Recuperación. Un fallo de red puede ser transitorio: reintentar con retroceso si la solicitud es idempotente. Un rechazo de seguridad no es transitorio y debe fallar de forma cerrada: no reintentar; corregir en su lugar la URL de destino o la política SSRF. Leer el mensaje y la lanzable previa para distinguir uno de otro.
  • Se lanza cuando. La solicitud en sí no puede enviarse porque está malformada, por ejemplo una URL no válida o una solicitud que no superó la validación SSRF antes de cualquier llamada de red.
  • Clase. Implementa Psr\Http\Client\RequestExceptionInterface de PSR-18.
  • Datos transportados. getRequest() devuelve el RequestInterface infractor; la causa subyacente, cuando está presente, es la lanzable previa encadenada. getContext() devuelve un arreglo vacío.
  • Recuperación. Es un defecto de entrada del llamador o de política, no un fallo transitorio. No reintentar sin cambios. Corregir la URL, las cabeceras o el cuerpo de la solicitud, o ajustar la lista de permitidos de SSRF si el destino está legítimamente autorizado, y luego volver a emitir la solicitud.
  • Se lanza cuando. Internamente, dentro de SecurityAwareHttpClient, para marcar un fallo de transporte interno genuinamente transitorio (DNS, conexión o tiempo de espera lanzado por el cliente PSR-18 interno) como apto para el presupuesto de reintentos acotado. Es la única clase apta para reintento que el bucle de reintentos del decorador reconoce; una excepción sin envolver (un rechazo de seguridad generado por el decorador) se trata como fatal.
  • Clase. Implementa Psr\Http\Client\NetworkExceptionInterface de PSR-18. Marcada @internal: se crea y se desenvuelve por completo dentro de SecurityAwareHttpClient y nunca escapa del decorador.
  • Datos transportados. getRequest() devuelve la solicitud fallida. La ClientExceptionInterface original del transporte interno se preserva como la lanzable previa encadenada (getPrevious()) y se vuelve a aflorar literalmente al llamador una vez agotado el presupuesto de reintentos, de modo que el contrato público de PSR-18 no cambia. getContext() devuelve un arreglo vacío.
  • Recuperación. El código de aplicación no captura este tipo directamente. Capturar la excepción interna que el decorador vuelve a aflorar tras gastar el presupuesto de reintentos, y tratar los fallos transitorios repetidos como un problema de disponibilidad aguas arriba.
  • Se lanza cuando. Un CircuitBreaker en el estado CircuitBreakerState::Open rechaza una llamada con fallo rápido, antes de cualquier invocación aguas abajo. Existe para que los llamadores distingan «el servicio remoto es inalcanzable ahora mismo» (un fallo de transporte transitorio, que conviene degradar) de «el fondo de conexiones se habría agotado con esta llamada» (fallo rápido, sin intento de red): la mitigación de denegación de servicio por lotes que requieren los clientes de Infraestructura de Clave Pública (PKI).
  • Clase. Extiende directamente RuntimeException, de modo que no transporta getContext().
  • Datos transportados. Dos propiedades públicas de readonly: $breakerName (el identificador del disyuntor abierto) y $secondsUntilHalfOpen (el enfriamiento aproximado que queda antes de que el disyuntor pase a semiabierto). El mensaje tiene la forma Circuit breaker "<name>" is OPEN (cooldown ~<n>s remaining); call rejected fail-fast.
  • Recuperación. No machacar el disyuntor: esperar al menos $secondsUntilHalfOpen antes de reintentar, o degradar la operación. No se intentó ninguna llamada de red, de modo que esto no es evidencia de que el servicio remoto en sí fallara; es contrapresión que protege el fondo de conexiones.
  • Se lanza cuando. Un emisor de eventos SIEM no puede persistir ni encadenar un registro. Aflora fallos a nivel de sistema de archivos (open, lock, seek, write, fflush, read) y fallos de integridad de la cadena de hash (chain: índice fuera de orden, registro de cola malformado o desviación de ida y vuelta de JSON) compartidos entre el registro de eventos de cadena de hash y los adaptadores del emisor de archivos JSON por líneas.
  • Clase. Extiende NextPdfException y redefine getContext().
  • Claves de contexto. operation (una de open, lock, seek, write, fflush, read, chain), path (la ruta del registro de destino) y detail (un detalle legible como recuentos de bytes o índice esperado frente al real). También se alcanzan a través de getOperation(), getPath() y getDetail(). El mensaje tiene la forma SIEM emitter <operation> failed for <path>: <detail>.
  • Recuperación. Es accionable por infraestructura o SecOps, no por la lógica de aplicación. Verificar el montaje del volumen de registro, los permisos del directorio, los descriptores de archivo disponibles y el estado del sistema de archivos. Un fallo de la operación chain indica una señal de manipulación o corrupción en el registro de auditoría y debe investigarse, no reintentarse de forma silenciosa.
  • Se lanza cuando. Un RenderManifest no puede construirse, deserializarse ni leerse a causa de un error estructural, de tipo o de compatibilidad de esquema. El manifiesto es un contrato público versionado que envía cada transporte (CLI, cola de Laravel, Symfony, la API SaaS), de modo que un manifiesto malformado o incompatible se aflora directamente en lugar de forzarse a valores predeterminados.
  • Clase. Extiende NextPdfException y redefine getContext(). Los constructores con nombre fijan un código legible por máquina estable en el espacio de nombres SPEC-MANIFEST-*:
    • RenderManifestException::shape()SPEC-MANIFEST-001: error de forma o de tipo durante RenderManifest::fromArray().
    • RenderManifestException::incompatibleVersion()SPEC-MANIFEST-002: versión mayor de esquema incompatible (no se puede leer).
    • RenderManifestException::missingField()SPEC-MANIFEST-003: campo obligatorio ausente durante la finalización del constructor.
    • RenderManifestException::unsupported()SPEC-MANIFEST-004: un manifiesto bien formado referencia una entrada o una plantilla que el representador actual no puede resolver (por ejemplo una entrada por URI o un motor de plantillas solo de anfitrión).
  • Claves de contexto. manifest_code (el identificador SPEC-MANIFEST-*) y reason (la descripción legible del fallo). También se alcanzan a través de getManifestCode() y getReason(). El mensaje tiene la forma [<code>] <reason>.
  • Recuperación. Ramificar según manifest_code. Para SPEC-MANIFEST-001 y SPEC-MANIFEST-003, corregir la carga útil del manifiesto (corregir el tipo del campo o aportar el campo ausente). Para SPEC-MANIFEST-002, regenerar el manifiesto contra una versión mayor de esquema compatible o actualizar el representador. Para SPEC-MANIFEST-004, aportar una entrada o un motor de plantillas que la edición actual pueda resolver.
  • Se lanza cuando. La inspección de PDF falla.
  • Clase. Extiende directamente RuntimeException (no NextPdfException), de modo que no transporta getContext().
  • Datos transportados. Dos propiedades públicas de readonly: $inspectCode (un código legible por máquina en el espacio de nombres INSPECT-*) y $retryable (un booleano que indica si el llamador debe reintentar; por ejemplo cuando un sidecar de inspección está temporalmente caído). La causa de origen, cuando está presente, es la lanzable previa encadenada.
  • Recuperación. Ramificar según $inspectCode para la clase de fallo específica. Cuando $retryable es true, reintentar con retroceso porque se espera que el fallo sea transitorio (como el reinicio de un sidecar); cuando es false, tratar la entrada o la configuración como el defecto y no reintentar sin cambios.
  • Se lanza cuando. ChaosScenarioRunner::writeReport() no puede persistir en disco el informe agregado de la jornada del caos. Es un reemplazo con tipo de dominio de un error de tiempo de ejecución genérico, de modo que los llamadores pueden capturar el fallo específico de disco del informe sin confundirlo con errores lanzados dentro de los propios simuladores de escenario (el ejecutor los captura como campos ChaosOutcome).
  • Clase. Extiende NextPdfException y redefine getContext().
  • Claves de contexto. output_path (la ruta absoluta que el ejecutor intentó escribir). También se alcanza a través de getOutputPath(). El mensaje tiene la forma ChaosScenarioRunner: failed to write report to "<path>".
  • Recuperación. Es un fallo del lado de la escritura del sumidero del informe, no de los escenarios. Verificar que el directorio de salida existe y es escribible y que hay espacio de disco disponible, y luego volver a ejecutar la escritura del informe. Los resultados del caos en sí no se ven afectados.
  • Se lanza cuando. Un extremo de obtención (por ejemplo un servicio de Generación Aumentada por Recuperación de Voyage) no está disponible y el sistema bien recurre al modo solo de caché, bien falla de forma cerrada.
  • Clase. Extiende NextPdfException y redefine getContext().
  • Claves de contexto. mode (el modo de operación tras el fallo: CACHED_ONLY cuando los resultados se sirven solo desde la caché semántica, o FAIL_CLOSED cuando la solicitud se rechaza por completo sin datos obsoletos) y endpoint (el extremo que se volvió inalcanzable). También se alcanzan a través de getMode() y getEndpoint(). El mensaje tiene la forma Retrieval endpoint "<endpoint>" is unavailable; operating in <mode> mode.
  • Recuperación. Leer mode para saber cómo se degradó el sistema. Bajo CACHED_ONLY, los resultados pueden estar obsoletos; refrescar una vez que el extremo se recupere. Bajo FAIL_CLOSED, la solicitud se rechazó por diseño y debe reintentarse después de que el extremo sea alcanzable. Restaurar la conectividad del extremo (red, credenciales, estado del servicio) antes de depender de una obtención fresca.