Every failure thrown by the SDK is an instance of PoliPage\PoliPageException with an errorCode. SDK-internal codes are lowercase; codes from the API are uppercase. Specialized subclasses under PoliPage\Exception\* narrow by HTTP status.
| Code | When |
invalid_options | Constructor or method arguments are missing or malformed (`apiKey is required`). |
network_error | TCP/TLS-level failure reaching the API, or a connection dropped while the answer is read (`Network request failed`; the HTTP library's exception is `getPrevious()`). Retryable. |
timeout | The request did not complete within `timeout` (`Request timed out after <ms>ms`). Retryable. |
aborted | Caller-driven cancellation. Not retryable. |
unknown_error | A catch-all for unexpected failures. |
DOWNLOAD_FAILED | The presigned PDF download failed: `Failed to download PDF: HTTP <status>` with the storage `status`; `Failed to download PDF: timeout` without one when it outlasted `timeout` (the whole download, or for `render->pdfStream()` the wait for the first byte or a gap between two chunks); `Failed to download PDF: network error` without one otherwise (no answer, or a connection dropped mid-body). Never retryable, whatever the storage status. |
invalid_response | A 2xx answer whose body is not JSON, from a method that expects JSON (`Invalid response: HTTP <status> body is not JSON`, the real 2xx as `status`). Raised as `InvalidResponseException`; `toPayload()` answers 502 for it. Not retryable. |
io_error | `renderToFile()` could not write the file (`Failed to write PDF: <reason>`, no status, PHP's error as `getPrevious()`); the target file is left untouched. Not retryable. |
INTERNAL_ERROR | The API answered 5xx, its error body was not JSON or could not be read (`HTTP <status>`, real status kept), or its response had an unexpected shape. Retryable on 5xx and 429. |
| Code | When |
MISSING_API_KEY | No API key in the request. |
INVALID_API_KEY | The API key is malformed or revoked. |
| Code | When |
ORGANIZATION_PAYMENT_GRACE | The organization is in payment grace: read-only, writes are refused. |
ORGANIZATION_CANCELLED | The organization has been cancelled: read-only until purge. |
ORGANIZATION_PURGED | The organization has been purged. |
ORGANIZATION_MIGRATING | The organization's storage is being migrated. Retryable. |
FORBIDDEN | A document of another organization, or of another environment than the key's. |
ENVIRONMENT_PROTECTED | `documents->delete` in a protected environment without the owner or admin role. |
THUMBNAILS_NOT_AVAILABLE | `documents->thumbnails` on a tier without thumbnails. |
| Code | When |
NOT_FOUND | Generic not found, e.g. an unknown route. |
PROJECT_NOT_FOUND | No project with this slug in the organization. |
PROJECT_NOT_IN_ENVIRONMENT | The project is not published in the key's environment, or was removed from it. |
TEMPLATE_NOT_FOUND | The template is absent from the project's copy in the key's environment. |
DOCUMENT_NOT_FOUND | No stored document matches the supplied id. |
DOCUMENT_GONE | The document was deleted, or is a `sandbox` document older than 30 days. |
| Code | When |
VALIDATION_ERROR | The request body failed validation, e.g. an unknown field or an out-of-range option. |
MISSING_DATA | The request body lacks the required `data` field. |
MISSING_TEMPLATE_SLUG | The template slug is missing. |
PROJECT_REQUIRED_FOR_DOCUMENT | A render was called with an empty `project`. |
TEMPLATE_ERROR | The engine rejected the template or its data. |
TEMPLATE_UNSAFE | The template, a partial or an SVG asset holds an injection attempt; the message (`detail`) names it. Not retryable. |
EMPTY_DOCUMENT | The render produced zero pages. |
ENVIRONMENT_MISMATCH | The request named another environment than the key's. The SDK never sends one. |
RENDER_BODY_TOO_LARGE | The request body is over the API's size limit. |
DOCUMENT_TOO_LARGE | The document exceeds an engine limit. |
| Code | When |
RATE_LIMIT_EXCEEDED | Too many requests for this key. Retryable. |
QUOTA_EXCEEDED | The organization's monthly quota is reached. Not retryable: it lasts until the monthly reset. |
OVERAGE_CAP_EXCEEDED | The overage cap is reached (paid tiers). Not retryable: it lasts until the monthly reset. |
| Code | When |
STORAGE_ACCESS_DENIED | The organization's own storage bucket refuses access (502). Not retryable: restore the bucket role, then call again. |
PUBLISH_IN_PROGRESS | The project is being published into this environment; honours `Retry-After`. Retryable. |
RENDER_TIMEOUT | The engine's time budget expired. Retryable. |
| Class | Extends | When |
|---|---|---|
| PoliPage\PoliPageException | RuntimeException | Base type for every SDK failure. |
| PoliPage\Exception\ApiStatusException | PoliPageException | Any non-2xx HTTP response. $status is non-null. |
| PoliPage\Exception\BadRequestException | ApiStatusException | HTTP 400. |
| PoliPage\Exception\AuthenticationException | ApiStatusException | HTTP 401. |
| PoliPage\Exception\PermissionDeniedException | ApiStatusException | HTTP 403. |
| PoliPage\Exception\NotFoundException | ApiStatusException | HTTP 404. |
| PoliPage\Exception\GoneException | ApiStatusException | HTTP 410. |
| PoliPage\Exception\RateLimitException | ApiStatusException | HTTP 429. |
| PoliPage\Exception\InternalServerException | ApiStatusException | HTTP 5xx. |
| PoliPage\Exception\ConnectionException | PoliPageException | Transport-layer failure (no HTTP response). |
| PoliPage\Exception\TimeoutException | ConnectionException | Per-request deadline exceeded. |
| PoliPage\Exception\InvalidResponseException | PoliPageException | A 2xx answer whose body is not JSON. $status is that 2xx. |