firecrawl/pdf-inspector · critical
merge never returns OCR-only content
Error message
merge never returns OCR-only content
What it means
In choose_adaptive_content (src/vision/fusion.rs), merge_native_and_ocr is documented to only return Native or Fused; the PageContentSource::Ocr arm is an unreachable!('merge never returns OCR-only content'). Hitting it means the merge function violated its contract and returned OCR-only content — a library bug, not a user-triggerable condition. It aborts the thread with a panic rather than producing a catchable error.
Source
Thrown at src/vision/fusion.rs:510
warning: format!(
"kept higher-quality {} after comparing OCR",
native.origin.description()
),
recommend_hosted: false,
};
}
let (markdown, source) = merge_native_and_ocr(native.markdown(), ocr);
let warning = match source {
PageContentSource::Native => format!(
"kept trustworthy {} because OCR duplicated its content",
native.origin.description()
),
PageContentSource::Fused => format!(
"fused trustworthy {} with complementary OCR",
native.origin.description()
),
PageContentSource::Ocr => unreachable!("merge never returns OCR-only content"),
};
AdaptiveContentChoice {
markdown,
source,
warning,
recommend_hosted: false,
}
}
#[derive(Debug, Clone, Copy)]
struct ContentOverlap {
shared_chars: usize,
}
fn content_overlap(first: &str, second: &str) -> ContentOverlap {
let mut first_counts = BTreeMap::<char, usize>::new();
for character in normalized_content_chars(first) {
*first_counts.entry(character).or_insert(0) += 1;View on GitHub (pinned to 636ca1a58b)
Solutions
- Revert or fix the change to merge_native_and_ocr so it can only return Native or Fused.
- If OCR-only output is now a legitimate outcome, replace the unreachable! with a real arm producing an Ocr warning instead of panicking.
- Add a unit test asserting merge_native_and_ocr never yields PageContentSource::Ocr for representative inputs.
- Reproduce with RUST_LOG=pdf_inspector::vision=debug and the failing PDF, then inspect the overlap/novelty values at the merge site.
Example fix
// before
PageContentSource::Ocr => unreachable!("merge never returns OCR-only content"),
// after
PageContentSource::Ocr => format!(
"kept OCR content for {} (no trustworthy native text)",
native.origin.description()
), Defensive patterns
Strategy: type-guard
Validate before calling
// Library-side guard: assert the merge contract before formatting the warning let source = merge_native_and_ocr(native.markdown(), ocr).1; debug_assert!(matches!(source, PageContentSource::Native | PageContentSource::Fused));
Type guard
fn merge_source_is_valid(source: PageContentSource) -> bool {
matches!(source, PageContentSource::Native | PageContentSource::Fused)
} Try / catch
// Not user-catchable (panic). Library-side: replace unreachable! with a graceful arm
let warning = match source {
PageContentSource::Ocr => {
log::warn!("merge returned OCR-only content; treating as fused");
"fused with OCR".to_string()
}
other => /* existing arms */
}; Prevention
- Never change merge_native_and_ocr to return PageContentSource::Ocr without updating this match.
- Add a unit test pinning the invariant that merge output is always Native or Fused.
- Prefer explicit error/warning arms over unreachable! for values that could become reachable after refactors.
- Run the vision fusion test suite after any change to overlap/novelty thresholds.
When it happens
Trigger: Only reachable if merge_native_and_ocr's internal logic is changed/buggy and returns PageContentSource::Ocr; cannot be triggered by any external input through documented APIs.
Common situations: Developers modifying merge_native_and_ocr (e.g. changing the overlap/novelty thresholds or returning Ocr for low-overlap pages) break the invariant; downstream maintainers hitting it after a refactor of the fusion module.
Related errors
AI-assisted analysis of firecrawl/pdf-inspector@636ca1a58b (2026-09-05).
Data as JSON: /api/errors/11bbbfbd0c17e46b.
Report an issue: GitHub.