we-promise/sure · error · Provider::Anthropic::Error

PDF exceeds Anthropic's 32 MB limit (#{pdf_content.bytesize}

Error message

PDF exceeds Anthropic's 32 MB limit (#{pdf_content.bytesize} bytes)

What it means

BankStatementExtractor#extract raises when pdf_content.bytesize exceeds MAX_PDF_BYTES (32 MiB). Anthropic's Messages API rejects requests larger than 32 MB total, and this extractor sends the whole statement as one native document block, so oversized PDFs are stopped locally with a clear message before wasting an API round-trip.

Source

Thrown at app/models/provider/anthropic/bank_statement_extractor.rb:22

  TOOL_NAME = "report_bank_statement".freeze

  # Mirrors Provider::Anthropic::PdfProcessor::MAX_PDF_BYTES.
  MAX_PDF_BYTES = 32 * 1024 * 1024

  attr_reader :client, :model, :pdf_content, :langfuse_trace, :family

  def initialize(client:, model:, pdf_content:, langfuse_trace: nil, family: nil)
    @client = client
    @model = model
    @pdf_content = pdf_content
    @langfuse_trace = langfuse_trace
    @family = family
  end

  def extract
    raise Provider::Anthropic::Error, "PDF content is required" if pdf_content.blank?
    if pdf_content.bytesize > MAX_PDF_BYTES
      raise Provider::Anthropic::Error,
            "PDF exceeds Anthropic's 32 MB limit (#{pdf_content.bytesize} bytes)"
    end

    span = langfuse_trace&.span(name: "extract_bank_statement_api_call", input: {
      model: model,
      pdf_size: pdf_content.bytesize
    })

    response = client.messages.create(
      model: model,
      max_tokens: max_tokens,
      system_: instructions,
      messages: [ { role: "user", content: user_content } ],
      tools: [ output_tool ],
      tool_choice: { type: "tool", name: TOOL_NAME, disable_parallel_tool_use: true }
    )

    parsed = extract_tool_input(response)

View on GitHub (pinned to e69894adb9)

Solutions

  1. Split the statement into smaller PDFs (per year/month) or export a shorter date range from the bank, then import each part.
  2. Compress/re-save the PDF (downsample scanned images, e.g. via ghostscript/qpdf) to get under 32 MiB.
  3. If you control the upload UI, enforce a client- and server-side size cap below 32 MiB with a friendly message so users never reach this raise.

Example fix

# before
statement.import! # 45 MB scanned PDF passes upload, dies at extract
# => PDF exceeds Anthropic's 32 MB limit (47185920 bytes)

# after
if pdf.bytesize > 32.megabytes
  render_error("Statement is too large (#{pdf.bytesize / 1.megabyte} MB). Please export a shorter date range or compress the PDF.")
else
  statement.import!
end
Defensive patterns

Strategy: validation

Validate before calling

MAX = 32.megabytes
if pdf.bytesize > MAX
  return error("Statement is #{pdf.bytesize / 1.megabyte} MB; limit is 32 MB. Split or compress it.")
end
extractor.extract

Try / catch

begin
  extractor.extract
rescue Provider::Anthropic::Error => e
  statement.mark_import_failed(reason: e.message) # user-actionable message included
end

Prevention

When it happens

Trigger: Uploading a very large bank statement PDF (>32 MiB — typically multi-year exports or scan-heavy statements with embedded images) through statement import; the guard fires before client.messages.create.

Common situations: Users exporting years of history from their bank; scanned (image-based) PDFs bloated to tens of MB; print-to-PDF with full-resolution page images; the app's own upload limit being higher than the model's request limit.

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/86eb58e9219c42cc. Report an issue: GitHub.