Skip to main content

Errors Reference

Every error response from the PDFCanon API uses the same JSON envelope:

{
"error": {
"type": "POLICY_REJECTION",
"code": "ENCRYPTED_PDF",
"message": "The uploaded PDF is encrypted or password-protected and cannot be processed.",
"stage": "intake",
"retryable": false
}
}
FieldTypeDescription
typestringBroad category. Stable across versions. See table below.
codestringSpecific machine-readable code. Stable across versions — safe to switch on.
messagestringHuman-readable description. May change wording — do not pattern-match.
stagestringPipeline stage that produced the error (intake, pipeline, etc.). Present on POLICY_REJECTION only.
retryablebooleantrue if a retry with the same input has a chance to succeed. Present on POLICY_REJECTION only.

The X-Request-Id response header is set on every error so you can correlate with our logs when filing a support ticket.

Error types — HTTP mapping

error.typeHTTP statusWhen it happens
POLICY_REJECTION422The PDF violates an intake or pipeline policy (size, encryption, etc.).
POLICY_VIOLATION400The request violates a locked normalization profile setting.
QUOTA_EXCEEDED402Monthly plan quota reached. Includes plan_tier, monthly_limit, current_usage.
RATE_LIMIT_EXCEEDED429Too many requests. Includes Retry-After, X-RateLimit-* headers.
ORGANIZATION_DEACTIVATED403The organization has been suspended.
INVALID_REQUEST400Malformed request (missing field, bad parameter).
UNAUTHORIZED401Missing or invalid API key / JWT.
NOT_IMPLEMENTED501Reserved for endpoints not yet available.
INTERNAL_ERROR500Unexpected server error. Always retry-safe with idempotency.

POLICY_REJECTION codes

Returned with HTTP 422 Unprocessable Entity.

Intake (stage = "intake")

coderetryableMeaning & suggested action
FILE_TOO_LARGEfalseThe upload exceeds the size limit for your plan. Compress the PDF or upgrade.
INVALID_MAGIC_NUMBERfalseThe bytes don’t start with %PDF-, or Content-Type isn’t application/pdf. Make sure you’re sending a real PDF (not, e.g., HTML or an EML attachment).
UNSUPPORTED_PDF_VERSIONfalsePDF version is outside the supported range (1.2 – 1.7).
ENCRYPTED_PDFfalseThe PDF is password-protected. Decrypt before submitting — PDFCanon will not attempt to break encryption.

Pipeline (stage = "pipeline")

coderetryableMeaning & suggested action
STRUCTURAL_REPAIR_FAILEDfalseThe PDF’s xref table or object stream is too corrupt to recover.
XFA_FORM_NOT_SUPPORTEDfalseThe PDF uses an XFA form. See Known Deviations.
DIGITAL_SIGNATURE_PRESENTfalseA digital signature was detected and your profile rejects signed PDFs. See the Digital Signature Policy.
FONT_NOT_EMBEDDEDfalseA required font is referenced but not embedded.
VERAPDF_VALIDATION_FAILEDfalseThe output failed PDF/A validation when PDF/A mode is enforced.
TOOLCHAIN_ERRORtrueqpdf or veraPDF returned an unexpected error. Safe to retry once.
Forward-compatibility

New code values may be added in any release without a major version bump. Always treat unknown codes as a generic POLICY_REJECTION and surface the message to the user.

QUOTA_EXCEEDED

{
"error": {
"type": "QUOTA_EXCEEDED",
"code": "QUOTA_EXCEEDED",
"message": "Monthly quota of 10000 PDFs reached.",
"plan_tier": "starter",
"monthly_limit": 10000,
"current_usage": 10000,
"upgrade_url": "/portal/billing"
}
}

RATE_LIMIT_EXCEEDED

{
"error": {
"type": "RATE_LIMIT_EXCEEDED",
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded.",
"retry_after": 30
}
}

Always respect the Retry-After response header (seconds). The X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers are also returned.

SDK error mapping

Every official SDK throws a typed PolicyRejectionException (or language equivalent) that exposes the code, message, and requestId. Switch on code — never on message.