we-promise/sure · error · Provider::Anthropic::Error
PDF content is required
Error message
PDF content is required
What it means
Provider::Anthropic::PdfProcessor#process raises "PDF content is required" when pdf_content is blank. The processor base64-encodes the PDF into a document block for the Messages API, so nil/empty content cannot proceed; the guard fires before the Langfuse span and the size check.
Source
Thrown at app/models/provider/anthropic/pdf_processor.rb:28
# minus a generous envelope reserve, so the encoded request stays under the
# limit. Guarding upstream also avoids base64-encoding an over-size blob in
# vain (peak heap before the API would reject it).
MAX_REQUEST_BYTES = 32 * 1024 * 1024
REQUEST_ENVELOPE_BYTES = 1 * 1024 * 1024
MAX_PDF_BYTES = (MAX_REQUEST_BYTES - REQUEST_ENVELOPE_BYTES) * 3 / 4
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 process
raise Provider::Anthropic::Error, "PDF content is required" if pdf_content.blank?
if pdf_content.bytesize > MAX_PDF_BYTES
raise Provider::Anthropic::Error,
"PDF is too large (#{pdf_content.bytesize} bytes); base64-encoded it would exceed Anthropic's 32 MB request limit"
end
span = langfuse_trace&.span(name: "process_pdf_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 }
)View on GitHub (pinned to e69894adb9)
Solutions
- Pass the real bytes: attachment.download or File.binread(path).
- Validate non-empty content where the upload is accepted (controller/model validation) so the job never gets blank input.
- If the source is empty, re-fetch/re-upload the document.
Example fix
# before processor.process # pdf_content: doc.file_path (String) # => PDF content is required # after processor = PdfProcessor.new(client, model: model, pdf_content: doc.file.download) processor.process
Defensive patterns
Strategy: validation
Validate before calling
content = doc.file.download
if content.blank?
return error("Document is empty — re-upload")
end
provider.process_pdf(pdf_content: content, model: model) Try / catch
begin processor.process rescue Provider::Anthropic::Error => e doc.mark_failed(reason: e.message) end
Prevention
- Check blob existence and size right after upload, not only at processing time.
- Pass binary content, not paths/URLs.
- Give documents a failed-state with the provider message so users can re-upload.
When it happens
Trigger: process is called with pdf_content: nil or "" — an attachment read that returned nil, a document record with empty content, or a caller passing a path/URL string where the binary body is expected.
Common situations: Active Storage blob not yet uploaded when the job runs; tempfile lifetime issues; download from a URL returned an empty body; refactor changed the parameter from bytes to something else.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- PDF content is required
- PDF is too large (#{pdf_content.bytesize} bytes); base64-enc
- Model did not invoke #{TOOL_NAME}
- No categories available for auto-categorization
- Model does not support PDF processing: #{effective_model}
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/e889263f076e21d3.
Report an issue: GitHub.