we-promise/sure · error · Provider::Openai::Error
Model does not support PDF/vision processing: #{effective_mo
Error message
Model does not support PDF/vision processing: #{effective_model} What it means
Raised by Provider::Openai#process_pdf when the effective model is not considered vision/PDF-capable. supports_pdf_processing? short-circuits to false when ENV OPENAI_SUPPORTS_PDF_PROCESSING is not one of true/1/yes (default is 'true'), returns true immediately for custom providers (uri_base set), and otherwise requires the model to start with one of VISION_CAPABLE_MODEL_PREFIXES: gpt-4o, gpt-4-turbo, gpt-4.1, gpt-5, o1, o3. The check runs against the effective model (the model: argument or @default_model), so a globally configured gpt-3.5-turbo or llama-style name on first-party OpenAI trips it.
Source
Thrown at app/models/provider/openai.rb:216
end
end
# Can be disabled via ENV for OpenAI-compatible endpoints that don't support vision
# Only vision-capable models (gpt-4o, gpt-4-turbo, gpt-4.1, etc.) support PDF input
def supports_pdf_processing?(model: @default_model)
return false unless ENV.fetch("OPENAI_SUPPORTS_PDF_PROCESSING", "true").to_s.downcase.in?(%w[true 1 yes])
# Custom providers manage their own model capabilities
return true if custom_provider?
# Check if the specified model supports vision/PDF input
VISION_CAPABLE_MODEL_PREFIXES.any? { |prefix| model.start_with?(prefix) }
end
def process_pdf(pdf_content:, model: "", family: nil)
with_provider_response do
effective_model = model.presence || @default_model
raise Error, "Model does not support PDF/vision processing: #{effective_model}" unless supports_pdf_processing?(model: effective_model)
trace = create_langfuse_trace(
name: "openai.process_pdf",
input: { pdf_size: pdf_content&.bytesize }
)
result = PdfProcessor.new(
client,
model: effective_model,
pdf_content: pdf_content,
custom_provider: custom_provider?,
langfuse_trace: trace,
family: family,
max_response_tokens: max_response_tokens
).process
upsert_langfuse_trace(trace: trace, output: result.to_h)
View on GitHub (pinned to e69894adb9)
Solutions
- Set the model to a vision-capable one for PDF work: model: "gpt-4.1" (or gpt-4o/gpt-5/o-series) when calling process_pdf.
- Update OPENAI_MODEL / Setting.openai_model if the default itself is legacy.
- If the flag was disabled, set OPENAI_SUPPORTS_PDF_PROCESSING=true (or remove it to accept the default).
- For genuinely new OpenAI model families, add the prefix to VISION_CAPABLE_MODEL_PREFIXES in app/models/provider/openai.rb:9.
Example fix
# before provider.process_pdf(pdf_content: pdf, model: "gpt-3.5-turbo") # after provider.process_pdf(pdf_content: pdf, model: "gpt-4.1")
Defensive patterns
Strategy: validation
Validate before calling
return unless provider.supports_model?(model) return unless provider.supports_pdf_processing?(model: model) # cheap pre-check before uploading bytes
Type guard
def vision_capable_model?(model)
%w[gpt-4o gpt-4-turbo gpt-4.1 gpt-5 o1 o3].any? { |p| model.to_s.start_with?(p) }
end Try / catch
begin
provider.process_pdf(pdf_content: bytes, model: model)
rescue Provider::Openai::Error => e
return redirect_to(root_path, alert: "Model cannot read PDFs; pick a vision-capable model") if e.message.start_with?("Model does not support")
raise
end Prevention
- Gate the PDF upload UI on supports_pdf_processing? instead of failing server-side.
- Keep the model prefix list updated when OpenAI ships new families, and default to gpt-4.1.
- Remember OPENAI_SUPPORTS_PDF_PROCESSING=false disables PDF processing globally, even for custom providers.
When it happens
Trigger: Setting.openai_model or OPENAI_MODEL set to an older model (gpt-3.5-turbo, gpt-4 non-turbo) and uploading a statement PDF; passing model: "deepseek-r1" without a custom uri_base; OPENAI_SUPPORTS_PDF_PROCESSING=false in the environment disabling PDF processing for everyone including custom providers.
Common situations: Org pins a cheap legacy model for categorization and PDF uploads then start failing; the feature flag env is flipped off during a cost review and later forgotten; new model names shipping after this prefix list was written (e.g. a future gpt-6) fail the prefix check until the list is updated.
Related errors
- Model does not support PDF processing: #{effective_model}
- {e.record.errors.full_messages.to_sentence.presence || e.mes
- OpenAI stream ended without a completion event. This usually
- PDF content is required
- PDF exceeds Anthropic's 32 MB limit (#{pdf_content.bytesize}
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/d3b1922bc1deb3da.
Report an issue: GitHub.