Stirling-Tools/Stirling-PDF · error · Error

OCR tools (OCRmyPDF or Tesseract) are not installed on the s

Error message

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.

What it means

Thrown by the OCR response handler when the backend response is not a PDF or ZIP (so it reads up to 1KB of text) and the text contains both 'OCR tools' and 'not installed'. This is the server's own error message surfacing that the running Stirling image (ultra-lite) was built without OCRmyPDF/Tesseract, so the OCR endpoint cannot function.

Source

Thrown at frontend/editor/src/core/hooks/tools/ocr/useOCROperation.ts:137

    } catch {
      /* ignore and try local extractor */
    }
    try {
      const local = await extractZipFile(blob); // local fallback
      if (local.length > 0) return local;
    } catch {
      /* fall through */
    }
    return [new File([blob], `ocr_${base}.zip`, { type: "application/zip" })];
  }

  // 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({

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Deploy the standard or fat Docker image, which bundle OCRmyPDF and Tesseract.
  2. If ultra-lite must stay, install OCRmyPDF/Tesseract into the container at build time (custom Dockerfile FROM the ultra-lite image).
  3. Hide/disable the OCR tool in the frontend when the backend advertises no OCR support (check app-config capability flags).
  4. Show the mapped user-facing message (already done) plus a docs link on how to switch images.

Example fix

// before — only thrown once the bad body is parsed
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.");
}

// after — also gate the tool up front so the call is never made
// (in the tool's isEnabled / validateParams):
if (!appConfig.ocrAvailable) {
  throw new Error("OCR is not available on this server image. Use the standard or fat Docker image.");
}
Defensive patterns

Strategy: validation

Validate before calling

// Gate OCR on backend capability before calling the endpoint
if (!appConfig.ocrAvailable) {
  // show 'OCR not available on this server image'; do not POST
}

Type guard

function ocrAvailable(cfg: { ocrAvailable?: boolean } | null | undefined): boolean {
  return !!cfg && cfg.ocrAvailable === true;
}

Try / catch

try {
  await runOcr();
} catch (e) {
  if (e instanceof Error && e.message.includes("OCR tools") && e.message.includes("not installed")) {
    toast.error("OCR is not installed. Use the standard or fat Docker image.");
  } else throw e;
}

Prevention

When it happens

Trigger: User runs OCR against a backend deployed from the ultra-lite Docker image, which intentionally omits OCR dependencies to minimize size; the OCR endpoint detects the missing binaries and returns an HTML/text error body instead of a PDF.

Common situations: Self-hosting with ultra-lite for size and forgetting OCR is excluded; ops switched images to ultra-lite for a smaller footprint; CI/test environment using ultra-lite by default.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/4e69b88894bee87f. Report an issue: GitHub.