- Analyzed ExtractionResult and ExtractionMetadata structure - Documented internal Diagnostic structure with code, offset, object_ref, message - Mapped DiagCode categories (STRUCT_*, STREAM_*, XREF_*, etc.) - Explained severity levels (Info, Warning, Error, Fatal) - Traced error flow from emission to string conversion - Identified key files: extract.rs, diagnostics.rs Closes bf-4482v
5.2 KiB
Extraction Result Error Structure Analysis
Overview
This document analyzes how errors and diagnostics are organized in the pdftract extraction result structure.
ExtractionResult Structure
The main ExtractionResult struct (defined in crates/pdftract-core/src/extract.rs) contains:
pub struct ExtractionResult {
pub fingerprint: String,
pub pages: Vec<PageResult>,
pub metadata: ExtractionMetadata,
pub signatures: Vec<SignatureJson>,
pub form_fields: Vec<FormFieldJson>,
pub links: Vec<LinkJson>,
pub attachments: Vec<AttachmentJson>,
pub threads: Vec<ThreadJson>,
pub javascript_actions: Vec<JavascriptActionJson>,
}
Error Reporting Locations
1. Document-Level Diagnostics
Location: ExtractionResult.metadata.diagnostics: Vec<String>
Purpose: Contains warnings and errors that affect the entire extraction process.
Examples:
- Tagged PDF detected (StructTree traversal deferred)
- Xref repaired via forward scan
- Coverage warnings
- Page range errors
2. Per-Page Errors
Location: PageResult.error: Option<String>
Purpose: Contains error messages when extraction fails for a specific page.
Structure:
pub struct PageResult {
pub index: usize,
pub page_number: u32,
pub page_label: Option<String>,
pub width: Option<f32>,
pub height: Option<f32>,
pub rotation: Option<u16>,
pub page_type: Option<String>,
pub spans: Vec<SpanJson>,
pub blocks: Vec<BlockJson>,
pub tables: Vec<TableJson>,
pub annotations: Vec<AnnotationJson>,
pub error: Option<String>, // ← Per-page error
}
3. Metadata Error Count
Location: ExtractionMetadata.error_count: usize
Purpose: Tracks the total number of pages that failed to extract.
Internal Diagnostic Structure
Before being converted to strings, diagnostics use the rich Diagnostic structure:
pub struct Diagnostic {
pub code: DiagCode, // Error type code
pub byte_offset: Option<u64>, // Location in file
pub object_ref: Option<ObjRef>, // PDF object reference
pub message: Cow<'static, str>, // Human-readable message
}
Diagnostic Code Categories
The DiagCode enum categorizes errors with prefixes:
| Category | Prefix | Description |
|---|---|---|
| Structure | STRUCT_* |
PDF structure errors (parser/object/document) |
| Stream | STREAM_* |
Stream decoder errors |
| XREF | XREF_* |
Cross-reference table errors |
| Encryption | ENCRYPTION_* |
Encryption-related errors |
| Page | PAGE_* |
Page-level errors |
| Font | FONT_* |
Font pipeline errors |
| Graphics State | GSTATE_* |
Graphics state errors |
| Layout | LAYOUT_* |
Layout and reading order errors |
| OCR | OCR_* |
OCR pipeline errors |
| Remote | REMOTE_* |
Remote source errors |
| MCP | MCP_* |
MCP server errors |
| Cache | CACHE_* |
Cache errors |
| Security | SECURITY_* |
Security-related diagnostics |
Severity Levels
Diagnostics have four severity levels:
-
Info — Does not affect output validity
- Examples:
XREF_REPAIRED,TAGGED_PDF_STRUCT_TREE_DEFERRED
- Examples:
-
Warning — Output is usable but degraded
- Examples:
STRUCT_INVALID_NAME,FONT_GLYPH_UNMAPPED,STREAM_DECODE_ERROR
- Examples:
-
Error — Output for this region/page is invalid; other regions OK
- Examples:
STREAM_BOMB,PAGE_OUT_OF_RANGE,REMOTE_FETCH_INTERRUPTED
- Examples:
-
Fatal — Extraction aborted, no usable output
- Examples:
ENCRYPTION_UNSUPPORTED,REMOTE_TLS_FAILED,REMOTE_DNS_FAILED
- Examples:
Error Flow
- Emission: During extraction,
Diagnosticstructs are emitted via theemit!()macro - Collection: Diagnostics are collected in
Vec<Diagnostic> - Conversion: Before returning
ExtractionResult, diagnostics are converted to strings:let diagnostics: Vec<String> = coverage_result .diagnostics .iter() .map(|d| d.message.as_ref().to_string()) .collect(); - Exposure: Final string messages are exposed in
ExtractionMetadata.diagnostics
Key Files
crates/pdftract-core/src/extract.rs- Main extraction pipeline, definesExtractionResultcrates/pdftract-core/src/diagnostics.rs- Diagnostic system, definesDiagnosticandDiagCodesrc/graphics_state/diagnostics.rs- Legacy diagnostic types (graphics state only)
Example Diagnostic
// Creating a diagnostic
Diagnostic::with_static(
DiagCode::StreamDecodeError,
12345, // byte offset
"zlib stream truncated mid-inflation"
)
// Converts to string in metadata:
// "STREAM_DECODE_ERROR: zlib stream truncated mid-inflation (byte offset 12345)"
Acceptance Criteria Status
✅ Error array structure understood
- Document-level diagnostics in
metadata.diagnostics - Per-page errors in
PageResult.error
✅ Error fields documented
- Internal
Diagnosticstruct with code, offset, object_ref, message - Final string representation in extraction result
✅ Relationship between errors and extraction phases clear
- Each diagnostic has a phase origin (e.g., "1.1", "1.5", "3.1")
- DiagCode category prefixes indicate which layer emitted the error
- Severity levels indicate impact on extraction result