Errors
Problem details, every problem code, and how to fix each one.
Every error answer is an RFC 9457 problem details object, sent as application/problem+json. Branch on code: it never changes for a given problem. detail says what to fix in plain words and may be reworded, so show it rather than parse it.
Problem details
| Field | Type | Description |
|---|---|---|
type | string | Stable problem type URI: urn:superpdf:problem:<code>. |
title | string | None |
status | integer | 400 to 599. |
detail | string | What went wrong and how to fix it. |
instance | string | URN for this problem occurrence. |
code | string | One of bad_request, unauthorized, forbidden, not_found, method_not_allowed, conflict, payload_too_large, unsupported_media_type, validation, operation_failed, too_many_jobs, busy, internal. |
request_id | string | None |
errors | array of objects | The fields to fix, for validation and conflict problems. |
errors[].field | string | None |
errors[].message | string | None |
Every answer, error or not, has an X-Request-Id header with the same value as request_id. Include it when you report a problem.
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json
{
"type": "urn:superpdf:problem:validation",
"title": "Invalid input",
"status": 422,
"detail": "Invalid input. pages: Page ranges must be between 1 and 4.",
"instance": "urn:superpdf:request:b20a5176-152e-4b22-9438-6a5e2bc969bd",
"code": "validation",
"request_id": "b20a5176-152e-4b22-9438-6a5e2bc969bd",
"errors": [
{
"field": "pages",
"message": "Page ranges must be between 1 and 4."
}
]
}Handle errors in code
curl -i http://127.0.0.1:7341/v1/tools/pdf_extract_pages \
-H "Authorization: Bearer $SUPERPDF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "input": "report.pdf", "pages": "2-9", "output": "excerpt.pdf" }'import { ApiError, callTool, type NewFile } from './superpdf.ts';
try {
await callTool<NewFile>('pdf_extract_pages', {
input: 'report.pdf',
pages: '2-9',
output: 'excerpt.pdf',
});
} catch (error) {
if (!(error instanceof ApiError)) throw error;
const { status, code, errors = [] } = error.problem;
console.log(`${status} ${code}`);
for (const { field, message } of errors) console.log(` ${field}: ${message}`);
}
from superpdf import ApiError, call_tool
try:
call_tool("pdf_extract_pages", {
"input": "report.pdf",
"pages": "2-9",
"output": "excerpt.pdf",
})
except ApiError as error:
problem = error.problem
print(problem["status"], problem["code"])
for item in problem.get("errors", []):
print(f" {item['field']}: {item['message']}")
package main
import (
"errors"
"fmt"
"log"
)
func main() {
_, err := CallTool[NewFile]("pdf_extract_pages", map[string]any{
"input": "report.pdf",
"pages": "2-9",
"output": "excerpt.pdf",
})
var problem *Problem
if !errors.As(err, &problem) {
log.Fatal(err) // no error, or the API could not be reached
}
fmt.Println(problem.Status, problem.Code)
for _, item := range problem.Errors {
fmt.Printf(" %s: %s\n", item.Field, item.Message)
}
}
Problem codes
| Status | code | title |
|---|---|---|
| 400 | bad_request | Malformed request |
| 401 | unauthorized | Authentication required |
| 403 | forbidden | Request not allowed |
| 404 | not_found | Resource not found |
| 405 | method_not_allowed | Method not allowed |
| 409 | conflict | Output already exists |
| 413 | payload_too_large | Request body too large |
| 415 | unsupported_media_type | Unsupported media type |
| 422 | validation | Invalid input |
| 422 | operation_failed | Operation failed |
| 429 | too_many_jobs | Too many jobs |
| 429 | busy | Too many tool calls |
| 500 | internal | Internal error |
400 bad_request
When: The body isn’t valid JSON.
Fix: Send one JSON object, encoded as UTF-8.
Example detail: The request body is not valid JSON.
401 unauthorized
When: The Authorization header is missing, isn’t a bearer token, or has the wrong token.
Fix: Send Authorization: Bearer with the token superpdf serve uses (SUPERPDF_API_TOKEN).
Example detail: The bearer token is not valid for this server. Use the token printed when superpdf serve started.
403 forbidden
When: The Host header isn’t 127.0.0.1 or localhost with the API’s port, or a web page sent the request from an origin that wasn’t allowed.
Fix: Call http://127.0.0.1:7341 directly. For a web app, start the API with --allow-origin and its origin.
Example detail: Requests from https://example.com are not allowed. Start the API with --allow-origin https://example.com to allow that website.
404 not_found
When: No such path, tool or job. Jobs are forgotten an hour after they finish and when the API stops.
Fix: Check the path against the endpoint reference, the tool name against GET /v1/tools, and the job id.
Example detail: There is no tool named pdf_compress. GET /v1/tools lists them.
405 method_not_allowed
When: The path exists but not with this method, such as GET on a tool.
Fix: Use the method in the Allow header: tools take POST.
Example detail: GET is not supported here. Use POST.
409 conflict
When: The output file is already there. superPDF never overwrites files.
Fix: Choose a new output name, or move the existing file first.
Example detail: Invalid input. output: appendix.pdf already exists. superPDF never overwrites files; choose a new name.
413 payload_too_large
When: The body is over 1 MB.
Fix: Send paths to files in the allowed folders, not file contents.
Example detail: The request body is larger than 1 MB. Send file paths, not file contents.
415 unsupported_media_type
When: The body isn’t sent with Content-Type: application/json.
Fix: Add that header; with curl, -H "Content-Type: application/json".
Example detail: Send the request body as JSON with Content-Type: application/json.
422 validation
When: A field is missing or out of range, a path is outside the allowed folders, or a file doesn’t exist. errors names each field.
Fix: Correct the fields listed in errors and send the request again.
Example detail: Invalid input. pages: Page ranges must be between 1 and 4.
422 operation_failed
When: The input was valid but the tool couldn’t process the document, for example a damaged file.
Fix: Read detail. Try pdf_repair on a damaged PDF, or open the file in Preview to check it.
Example detail: This file is too damaged to repair.
429 too_many_jobs
When: 100 jobs are already waiting or running.
Fix: Wait for jobs to finish (GET /v1/jobs), then send the job again.
Example detail: 100 jobs are already waiting. Try again when some have finished.
429 busy
When: Tool calls run 4 at a time (LibreOffice conversions 2 at a time) and the rest wait their turn; this answer means 64 calls are already waiting.
Fix: Wait for some calls to finish, then send the request again. For long work, use a job.
Example detail: superPDF is busy: 4 tool calls running and 64 waiting. Try again when some have finished.
500 internal
When: A bug in superPDF.
Fix: The Terminal window running superpdf serve shows the details. Report it with the request_id.
Example detail: The server failed unexpectedly. Details are in the terminal running superpdf serve.
Retrying
429: wait for jobs (too_many_jobs) or tool calls (busy) to finish, then send the request again.500and network errors: safe to retry once; if it happens again, report it with therequest_id.4xxotherwise: the same request will fail the same way. Change it first.- A tool that writes a file isn’t repeatable: if a response was lost after the file was written, a retry gets
409. Check whether the output exists before you retry.