Skip to content

Errors

Every failure returned by the SDK is a *polipage.Error. Use errors.As to extract typed fields and errors.Is against the package-level sentinels (ErrUnauthorized, ErrDocumentGone, …) for quick branching.

A sentinel matches by code, not by HTTP status. ErrUnauthorized matches MISSING_API_KEY and INVALID_API_KEY, and ErrRateLimit matches QUOTA_EXCEEDED and OVERAGE_CAP_EXCEEDED. To catch every 429, use the IsRateLimitError() method; for a failed render, compare Code with ErrCodeProjectNotFound, ErrCodeProjectNotInEnvironment or ErrCodeTemplateNotFound.

var perr *polipage.Error
if errors.As(err, &perr) {
fmt.Println(perr.Code, perr.StatusCode, perr.RequestID, perr.Message)
}

*Error implements Unwrap, so errors.Unwrap(err) gives you the underlying I/O / context cause when present.

These originate inside the SDK before any HTTP call (or in response to a network-layer failure). They are lowercase.

CodeWhenRecovery
invalid_optionsThe options passed to NewClient (or a per-call WithX option) are invalid. A missing or empty API key gives the message `apiKey is required`.Fix the call site. Surfaced on the first method call.
network_errorTCP/TLS-layer failure reaching the API. The message is `Network request failed`; the net/http error is the `Cause`.Automatically retried up to WithMaxRetries times.
timeoutThe request did not complete within the configured WithTimeout. The message is `Request timed out after <ms>ms`.Automatically retried up to WithMaxRetries times. Raise WithTimeout if it keeps tripping.
abortedThe caller-supplied context was cancelled, during a request, a retry wait or the PDF download. The message is `Request was aborted`.Not retryable. Surface to the caller.
io_failedA local filesystem write failed inside RenderToFile.Fix the path / permissions. Unwrap to inspect the os error.
DOWNLOAD_FAILEDFetching a presigned PDF URL failed: `Failed to download PDF: HTTP <status>` with the storage `StatusCode` (an expired URL gets 403), or `Failed to download PDF: network error` without one, also when the connection drops while the body is read.Never retryable, whatever the storage status. Call Documents.Get to refresh the presigned URL and retry.

Returned by the Poli Page API. Uppercase, snake-case. The SDK forwards the code verbatim.

CodeWhenRecovery
INVALID_API_KEYThe API key is malformed or revoked.Rotate the key in the dashboard.
MISSING_API_KEYNo API key was provided in the request.Check WithAPIKey was supplied to NewClient.
PROJECT_NOT_FOUNDNo project matches the slug.Check the slug. If getting-started was renamed or deleted, use a fresh organization.
PROJECT_NOT_IN_ENVIRONMENTThe project is not published in the key's environment.Publish the project to that environment, or use a key of the environment it is published in.
TEMPLATE_NOT_FOUNDThe published project has no template with that slug.Check the template slug.
DOCUMENT_NOT_FOUNDNo stored document matches the documentId.Check the id.
DOCUMENT_GONEThe document was deleted or has expired (sandbox documents expire after 30 days).Render it again.
VALIDATION_ERRORThe request failed validation.Read Message for the failing field.
MISSING_DATAThe request body lacks the required Data field.Pass a non-nil Data on every render call (an empty map is fine).
QUOTA_EXCEEDEDThe organization's monthly quota is exhausted (429).Not retried: it lasts until the monthly reset. Upgrade the plan for more renders.
OVERAGE_CAP_EXCEEDEDThe organization reached its overage cap (429).Not retried: it lasts until the monthly reset. Raise the cap in the dashboard.
STORAGE_ACCESS_DENIEDThe organization's own storage bucket refuses access (502).Not retried: restore the bucket role, then call again.
RATE_LIMIT_EXCEEDEDToo many requests (429).Retried like any 429, honoring Retry-After.
ORGANIZATION_PAYMENT_GRACEThe organization's billing is past due.Update the payment method in the dashboard.
PUBLISH_IN_PROGRESSA publish holds the project in the key's environment (503).Retried like any 5xx, honoring Retry-After.
INTERNAL_ERRORThe API returned 5xx. Also the code of an error answer whose body is not JSON (a gateway page) or fails while it is read, with its real status and the message `HTTP <status>`.Automatically retried; contact support if it persists.

The full list of API codes lives in the reference.

package main
import (
"context"
"errors"
"fmt"
"os"
"github.com/poli-page/sdk-go"
"github.com/poli-page/sdk-go/option"
)
func main() {
client := polipage.NewClient(option.WithAPIKey(os.Getenv("POLI_PAGE_API_KEY")))
_, err := client.Render.PDF(context.Background(), polipage.RenderInput{
Project: "billing",
Template: "invoice",
Data: map[string]any{"invoiceNumber": "INV-001"},
})
if err != nil {
var perr *polipage.Error
if errors.As(err, &perr) {
if perr.IsRateLimitError() {
// RATE_LIMIT_EXCEEDED after the SDK's built-in retries, or
// QUOTA_EXCEEDED / OVERAGE_CAP_EXCEEDED, which the SDK never
// retries: queue the job for later, or report it as here.
fmt.Fprintln(os.Stderr, "rate limited, try again later; request id:", perr.RequestID)
os.Exit(1)
}
fmt.Println("code:", perr.Code, "request id:", perr.RequestID)
}
panic(err)
}
}