Stirling-Tools/Stirling-PDF · error · Error
Response is not a valid PDF. Header: "${head}"
Error message
Response is not a valid PDF. Header: "${head}" What it means
Thrown by the OCR response handler when the blob's first 8 bytes are neither a PDF magic ('%PDF') nor a ZIP magic ('PK'), and the first 1KB does not look like an error/exception/HTML body. It is the 'unrecognized response' fallback — the server returned something, but it is neither a valid OCR output nor a recognizable error.
Source
Thrown at frontend/editor/src/core/hooks/tools/ocr/useOCROperation.ts:147
}
// Not a PDF: surface error details if present
if (!head.startsWith("%PDF")) {
const textBuf = await blob.slice(0, 1024).arrayBuffer();
const text = new TextDecoder().decode(new Uint8Array(textBuf));
if (/error|exception|html/i.test(text)) {
if (text.includes("OCR tools") && text.includes("not installed")) {
throw new Error(
"OCR tools (OCRmyPDF or Tesseract) are not installed on the server. Use the standard or fat Docker image instead of ultra-lite, or install OCR tools manually.",
);
}
const title =
text.match(/<title[^>]*>([^<]+)<\/title>/i)?.[1] ||
text.match(/<h1[^>]*>([^<]+)<\/h1>/i)?.[1] ||
"Unknown error";
throw new Error(`OCR service error: ${title}`);
}
throw new Error(`Response is not a valid PDF. Header: "${head}"`);
}
const originalName = originalFiles[0].name;
return [new File([blob], originalName, { type: "application/pdf" })];
};
// Static configuration object (without t function dependencies)
export const ocrOperationConfig = defineSingleFileTool({
validateParams: validateOCRParameters,
buildFormData: buildOCRFormData,
toApiParams: ocrToApiParams,
fromApiParams: ocrFromApiParams,
operationType: "ocr",
endpoint: ENDPOINT,
defaultParameters,
});
export const useOCROperation = () => {View on GitHub (pinned to 9ef20dcab8)
Solutions
- Log the full Content-Type, Content-Length, and first bytes for the failing response to classify it.
- Check backend logs — a 200 with empty body usually means the controller returned before writing output (early return / swallowed exception).
- Verify network/proxy is not truncating the body (compare Content-Length to actual bytes).
- Treat HTTP non-2xx explicitly before parsing the body so error responses are not misclassified as 'not a PDF'.
Example fix
// before
throw new Error(`Response is not a valid PDF. Header: "${head}"`);
// after — include size + content-type for diagnosis
throw new Error(`Response is not a valid PDF. Header: "${head}" (size=${blob.size}, type=${blob.type})`); Defensive patterns
Strategy: validation
Validate before calling
// Reject non-PDF responses before parsing
if (!head.startsWith("%PDF") && !head.startsWith("PK")) {
const ct = response.headers?.["content-type"];
if (!ct?.includes("pdf") && !ct?.includes("zip")) {
// classify as protocol error with status + size, do not attempt PDF parsing
}
} Try / catch
try {
await runOcr();
} catch (e) {
if (e instanceof Error && e.message.startsWith("Response is not a valid PDF.")) {
// log size/type and check backend for empty-body bug
console.error("Unrecognized OCR response", { size: blob.size, type: blob.type });
toast.error("OCR returned an unexpected response.");
} else throw e;
} Prevention
- Verify the endpoint actually returned a PDF (check Content-Type/Length).
- Handle HTTP non-2xx explicitly so error responses are not misclassified as 'not a PDF'.
- Log the raw response metadata when this fires to classify the unknown format.
When it happens
Trigger: Server returned a 200 with an empty body or whitespace; response is a binary fragment of an unknown format; a CDN/cache layer returned a truncated response; content-encoding/transfer corruption truncated the magic bytes; the OCR endpoint returned an octet-stream that is not actually a PDF.
Common situations: Empty 200 from a misconfigured endpoint; truncated response on a flaky connection; the backend changed its output format without the frontend handler being updated.
Related errors
- OCR service error: ${title}
- The server processed the request but returned no files.
- No team resolved yet
- No automation configuration provided
- Unsupported conversion format
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/cf448e81d94372df.
Report an issue: GitHub.