Runtime and support errors
These entries document the exceptions raised by the runtime support layer: the degradation policy, the cURL-backed HTTP transport, the resilience circuit breaker, the Security Information and Event Management (SIEM) emitter, the render manifest, PDF inspection, and the chaos-engineering subsystem.
Most NextPDF exceptions extend NextPdfException, which implements
ContextAwareExceptionInterface and exposes getContext(): array for
structured diagnostic logging. A subclass populates that array only when it
overrides getContext(); the base returns an empty array. Three exceptions on
this page (DegradedException, CircuitBreakerOpenException, and InspectException) extend PHP’s
RuntimeException directly and expose their data through public readonly
properties instead of getContext(). Each entry below names the exact
properties or context keys the class carries, taken from source.
Degradation policy
Section titled “Degradation policy”DegradedException
Section titled “DegradedException”- Thrown when. The rendering pipeline encounters a degraded capability
that violates the active degradation policy. Under
DegradationPolicy::Strict, any high-impact degradation (ComplianceRisk,SemanticLoss, orBlocking) raises it; underDegradationPolicy::Balanced, only aBlockingimpact raises it. - Class. Extends
RuntimeExceptiondirectly (notNextPdfException), so it carries nogetContext(). - Data carried. Two public
readonlyproperties:$capability(theCapabilityvalue object that triggered the rejection, including itsid,status,reason,fallbackTarget, andimpact) and$policy(theDegradationPolicyactive at rejection time). The message has the formFeature "<id>" is <status>: <reason> (policy: <policy>). - Recovery. Inspect
$capabilityto identify the missing feature and its cause. Either install the component that the capability requires, accept a lower-impact configuration, or relax the policy fromStricttoBalancedwhen the degradation is acceptable for the use case. Call$capability->isAvailable()/isDegraded()to drive user-facing messaging.
HTTP transport
Section titled “HTTP transport”These three exceptions originate in the cURL-backed PSR-18 client and its
security-aware decorator. The first two extend NextPdfException but do not
override getContext(), so their getContext() returns an empty array;
diagnostic data is reached through the PSR-18 getRequest() accessor and the
chained previous throwable.
CurlNetworkException
Section titled “CurlNetworkException”- Thrown when. The HTTP request cannot be completed because of a network-level fault: Domain Name System (DNS) resolution failure, connection timeout, or Transport Layer Security (TLS) handshake error. It is also the class the security-aware decorator raises for a security rejection (Server-Side Request Forgery refusal, DNS-rebinding refusal, or a denied redirect).
- Class. Implements PSR-18
Psr\Http\Client\NetworkExceptionInterface. - Data carried.
getRequest()returns the failedRequestInterface. The originating transport error, when present, is the chained previous throwable.getContext()returns an empty array (the base default). - Recovery. A network fault may be transient — retry with backoff if the request is idempotent. A security rejection is not transient and must fail closed: do not retry; correct the target URL or the SSRF policy instead. Read the message and previous throwable to tell the two apart.
CurlRequestException
Section titled “CurlRequestException”- Thrown when. The request itself cannot be sent because it is malformed, for example an invalid URL or a request that failed SSRF validation before any network call.
- Class. Implements PSR-18
Psr\Http\Client\RequestExceptionInterface. - Data carried.
getRequest()returns the offendingRequestInterface; the underlying cause, when present, is the chained previous throwable.getContext()returns an empty array. - Recovery. This is a caller-input or policy defect, not a transient fault. Do not retry unchanged. Fix the request URL, headers, or body, or adjust the SSRF allowlist if the target is legitimately permitted, then re-issue the request.
TransientHttpException
Section titled “TransientHttpException”- Thrown when. Internally, inside
SecurityAwareHttpClient, to mark a genuinely transient inner-transport fault (DNS, connection, or timeout raised by the inner PSR-18 client) as eligible for the bounded retry budget. It is the only retry-eligible class the decorator’s retry loop recognises; an unwrapped exception (a decorator-raised security rejection) is treated as fatal. - Class. Implements PSR-18
Psr\Http\Client\NetworkExceptionInterface. Marked@internal— it is created and unwrapped entirely withinSecurityAwareHttpClientand never escapes the decorator. - Data carried.
getRequest()returns the failed request. The original inner-transportClientExceptionInterfaceis preserved as the chained previous throwable (getPrevious()) and re-surfaced verbatim to the caller once the retry budget is exhausted, so the public PSR-18 contract is unchanged.getContext()returns an empty array. - Recovery. Application code does not catch this type directly. Catch the re-surfaced inner exception that the decorator returns after the retry budget is spent, and treat repeated transient failures as an upstream availability problem.
Resilience
Section titled “Resilience”CircuitBreakerOpenException
Section titled “CircuitBreakerOpenException”- Thrown when. A
CircuitBreakerin theCircuitBreakerState::Openstate rejects a call fail-fast, before any downstream invocation. It exists to let callers distinguish “the remote service is unreachable right now” (a transient transport fault, worth degrading) from “the connection pool would have been exhausted by this call” (fail-fast, no network attempted) — the batch denial-of-service mitigation required for Public Key Infrastructure (PKI) clients. - Class. Extends
RuntimeExceptiondirectly, so it carries nogetContext(). - Data carried. Two public
readonlyproperties:$breakerName(the identifier of the open breaker) and$secondsUntilHalfOpen(the approximate cooldown remaining before the breaker transitions to half-open). The message has the formCircuit breaker "<name>" is OPEN (cooldown ~<n>s remaining); call rejected fail-fast. - Recovery. Do not hammer the breaker — wait at least
$secondsUntilHalfOpenbefore retrying, or degrade the operation. No network call was attempted, so this is not evidence the remote service itself failed; it is back-pressure protecting the connection pool.
Observability
Section titled “Observability”SiemEmitterException
Section titled “SiemEmitterException”- Thrown when. A SIEM event emitter cannot persist or chain a record. It
surfaces filesystem-level failures (
open,lock,seek,write,fflush,read) and hash-chain integrity faults (chain: out-of-order index, malformed tail record, or JSON round-trip drift) shared across the hash-chain event log and the JSON-lines file emitter adapters. - Class. Extends
NextPdfExceptionand overridesgetContext(). - Context keys.
operation(one ofopen,lock,seek,write,fflush,read,chain),path(the target log path), anddetail(a human-readable detail such as byte counts or expected-versus-actual index). These are also reachable throughgetOperation(),getPath(), andgetDetail(). The message has the formSIEM emitter <operation> failed for <path>: <detail>. - Recovery. This is actionable by infrastructure or SecOps, not by
application logic. Verify the log-volume mount, directory permissions,
available file descriptors, and filesystem health. A
chainoperation failure indicates a tamper or corruption signal in the audit log and should be investigated, not silently retried.
Render manifest
Section titled “Render manifest”RenderManifestException
Section titled “RenderManifestException”- Thrown when. A
RenderManifestcannot be constructed, deserialized, or read because of a structural, type, or schema-compatibility error. The manifest is a versioned public contract submitted by every transport (CLI, Laravel queue, Symfony, the SaaS API), so a malformed or incompatible manifest is surfaced directly rather than coerced to defaults. - Class. Extends
NextPdfExceptionand overridesgetContext(). Named constructors set a stable machine-readable code in theSPEC-MANIFEST-*namespace:RenderManifestException::shape()→SPEC-MANIFEST-001— shape or type error duringRenderManifest::fromArray().RenderManifestException::incompatibleVersion()→SPEC-MANIFEST-002— incompatible major schema version (cannot be read).RenderManifestException::missingField()→SPEC-MANIFEST-003— required field missing during builder finalization.RenderManifestException::unsupported()→SPEC-MANIFEST-004— a well-formed manifest references an input or template the current renderer cannot resolve (for example a URI input or a host-only template engine).
- Context keys.
manifest_code(theSPEC-MANIFEST-*identifier) andreason(the human-readable failure description). These are also reachable throughgetManifestCode()andgetReason(). The message has the form[<code>] <reason>. - Recovery. Branch on
manifest_code. ForSPEC-MANIFEST-001andSPEC-MANIFEST-003, fix the manifest payload (correct the field type or supply the missing field). ForSPEC-MANIFEST-002, regenerate the manifest against a supported major schema version or upgrade the renderer. ForSPEC-MANIFEST-004, supply an input or template engine the current edition can resolve.
Inspection
Section titled “Inspection”InspectException
Section titled “InspectException”- Thrown when. PDF inspection fails.
- Class. Extends
RuntimeExceptiondirectly (notNextPdfException), so it carries nogetContext(). - Data carried. Two public
readonlyproperties:$inspectCode(a machine-readable code in theINSPECT-*namespace) and$retryable(a boolean indicating whether the caller should retry — for example when an inspection sidecar is temporarily down). The originating cause, when present, is the chained previous throwable. - Recovery. Branch on
$inspectCodefor the specific failure class. When$retryableistrue, retry with backoff because the failure is expected to be transient (such as a sidecar restart); whenfalse, treat the input or configuration as the defect and do not retry unchanged.
Chaos engineering
Section titled “Chaos engineering”ChaosReportWriteException
Section titled “ChaosReportWriteException”- Thrown when.
ChaosScenarioRunner::writeReport()cannot persist the aggregated chaos-day report to disk. It is a domain-typed replacement for a generic runtime error, so callers can catch the specific report-disk failure without conflating it with errors raised inside the scenario simulators themselves (the runner captures those asChaosOutcomefields). - Class. Extends
NextPdfExceptionand overridesgetContext(). - Context keys.
output_path(the absolute path the runner attempted to write). It is also reachable throughgetOutputPath(). The message has the formChaosScenarioRunner: failed to write report to "<path>". - Recovery. This is a write-side failure of the report sink, not of the scenarios. Verify the output directory exists and is writable and that disk space is available, then re-run the report write. The chaos outcomes themselves are unaffected.
RetrievalUnavailableException
Section titled “RetrievalUnavailableException”- Thrown when. A retrieval endpoint (for example a Voyage Retrieval Augmented Generation service) is unavailable and the system either falls back to cached-only mode or fails closed.
- Class. Extends
NextPdfExceptionand overridesgetContext(). - Context keys.
mode(the operating mode after the failure —CACHED_ONLYwhen results are served from the semantic cache only, orFAIL_CLOSEDwhen the request is refused entirely with no stale data) andendpoint(the endpoint that became unreachable). These are also reachable throughgetMode()andgetEndpoint(). The message has the formRetrieval endpoint "<endpoint>" is unavailable; operating in <mode> mode. - Recovery. Read
modeto learn how the system degraded. UnderCACHED_ONLY, results may be stale; refresh once the endpoint recovers. UnderFAIL_CLOSED, the request was refused by design and must be retried after the endpoint is reachable. Restore endpoint connectivity (network, credentials, service health) before depending on fresh retrieval.