Skip to content
getnextpdf.com

Accelerator errors

These five exceptions surface failures from the optional Spectrum (Prism) hardware-accelerator sidecar. The sidecar is reached over HTTP through NextPDF\Accelerator\SpectrumClient; error responses carry a machine-readable SPEC-* code from a canonical taxonomy, and the client maps that code onto one of the exception types below.

Unlike most NextPDF exceptions, the Accelerator exceptions do not implement getContext(). They extend PHP’s RuntimeException and expose their state as typed, readonly public properties. Discriminate error domains by matching the specCode prefix (for example str_starts_with($e->specCode, 'SPEC-AUTH-')), not by catching subclasses — the subclass hierarchy is internal and may change in minor versions.

SpectrumApiException is the base type for every sidecar error response. It is thrown directly for any SPEC-* code that has no more specific subclass, and it is the type you catch to handle all sidecar errors at once.

  • The sidecar returns a structured SPEC-* error body. SpectrumResponseParser decodes the body and throws this type for all codes except SPEC-AUTH-* and SPEC-OOM-* (which map to subclasses below). Documented mappings to this base type include SPEC-INDEX-* (collection index), SPEC-KMS-* (key-management provider), SPEC-OCR-*, SPEC-MODEL-*, and SPEC-BILLING-*.
  • SPEC-IO-001 — the response body is not valid JSON (httpStatus 502).
  • SPEC-IO-002 — the sidecar API version is incompatible with the configured minApiVersion.
  • SPEC-SEC-001 — a document payload exceeds the configured size budget (SpectrumSecurityPolicy::validatePayloadSize()).
  • SPEC-SEC-003 — a workspace path fails the traversal check (SpectrumSecurityPolicy::validateWorkspacePath()).
  • SPEC-SEC-004 — a job identifier is empty, too long, or contains characters outside the opaque-ID allowlist (SpectrumSecurityPolicy::validateJobId()).
PropertyTypeMeaning
specCodestringMachine-readable SPEC-* error code (for example SPEC-INDEX-003).
httpStatusintHTTP status the sidecar returned; defaults to 500. Also used as the exception code.
retryableboolWhether the operation may be safely retried. Defaults to false.
traceId?stringCorrelation trace ID from the X-Trace-Id response header, or null.

The message is composed as "[{specCode}] {message}". Three helper predicates classify common domains: isKmsError() (SPEC-KMS-*), isIndexError() (SPEC-INDEX-*), and isOcrError() (SPEC-OCR-*).

  1. Read specCode to identify the failing domain; branch on its prefix.
  2. Honor retryable: retry only when it is true, and never on a SPEC-SEC-* or SPEC-IO-002 code, which signal configuration or compatibility defects.
  3. Capture traceId in your logs to correlate the failure with sidecar-side diagnostics in a defect report.

The following types are final subclasses of SpectrumApiException. Catch SpectrumApiException (or match on specCode) rather than these directly.

Thrown for SPEC-AUTH-* codes, indicating a license, token, or deployment binding failure. SpectrumResponseParser raises it whenever the response code starts with SPEC-AUTH-.

Documented causes include SPEC-AUTH-001 (invalid license Ed25519 signature), SPEC-AUTH-002 (license expired and outside the grace period), SPEC-AUTH-003 (deployment slot mismatch), SPEC-AUTH-004 (invalid JWT Bearer token), SPEC-AUTH-006 (license degraded, grace expired), and SPEC-AUTH-007 (feature not included in the purchased license).

It carries the same properties as the base type, but the constructor pins retryable to false and defaults httpStatus to 403.

Recovery. These errors are never retryable without operator intervention. Renew or correct the license, refresh the Bearer token, or align the deployment slot, then re-run the call.

Thrown for SPEC-OOM-* codes when GPU or CPU memory is exhausted. SpectrumResponseParser raises it for any SPEC-OOM- prefix, and the DegradePolicy::FailFast setting raises it instead of silently downgrading to a lower hardware tier.

The constructor pins retryable to true and defaults httpStatus to 503.

Recovery. This exception is retryable. Queue the job and retry after other jobs complete and free resources, or relax DegradePolicy to AllowWithLog / WarnAndProceed if a downgraded tier is acceptable for the workload.

Thrown when a sidecar response parses as JSON but does not match the expected protocol shape. It always uses specCode SPEC-IO-003 and httpStatus 502, with retryable pinned to false.

This is distinct from SPEC-IO-001 (invalid JSON): here the JSON is well-formed but structurally wrong, which typically indicates a proxy or gateway rewriting the body, an incompatible sidecar version, or a corrupted response.

Recovery. Not retryable — the response shape is deterministic for a given sidecar version. Verify the sidecar version against the client’s minApiVersion, inspect any intermediary proxy or gateway, then re-deploy a compatible sidecar.

SpectrumNotAvailableException extends RuntimeException directly and is not part of the SpectrumApiException hierarchy. It signals that the sidecar is unreachable or failed a health check, before any SPEC-* error body could be returned.

  • The circuit breaker is open, or all retry attempts are exhausted (SpectrumClient).
  • An HTTP transport error occurs while contacting the sidecar; the underlying PSR-18 ClientExceptionInterface is chained as the previous exception.
  • A server-sent-events stream is requested while the sidecar reports itself unavailable (SseStreamClient).

This type carries no SPEC-* metadata. The message is composed as "Spectrum sidecar unavailable: {reason}", with an optional integer code and a chained previous throwable.

Catch this when Spectrum is optional and fall back to PHP-native processing (graceful degradation). When Spectrum is required, confirm the sidecar is up and reachable, then re-run the call.