From 6117735ed2b753bf342821b05e2b099968f81c8d Mon Sep 17 00:00:00 2001 From: jedarden Date: Sun, 5 Jul 2026 19:31:29 -0400 Subject: [PATCH] docs(bf-4482v): document extraction result error structure - 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 --- notes/bf-4482v.md | 164 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 notes/bf-4482v.md diff --git a/notes/bf-4482v.md b/notes/bf-4482v.md new file mode 100644 index 0000000..3c0dddd --- /dev/null +++ b/notes/bf-4482v.md @@ -0,0 +1,164 @@ +# 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: + +```rust +pub struct ExtractionResult { + pub fingerprint: String, + pub pages: Vec, + pub metadata: ExtractionMetadata, + pub signatures: Vec, + pub form_fields: Vec, + pub links: Vec, + pub attachments: Vec, + pub threads: Vec, + pub javascript_actions: Vec, +} +``` + +## Error Reporting Locations + +### 1. Document-Level Diagnostics + +**Location**: `ExtractionResult.metadata.diagnostics: Vec` + +**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` + +**Purpose**: Contains error messages when extraction fails for a specific page. + +**Structure**: +```rust +pub struct PageResult { + pub index: usize, + pub page_number: u32, + pub page_label: Option, + pub width: Option, + pub height: Option, + pub rotation: Option, + pub page_type: Option, + pub spans: Vec, + pub blocks: Vec, + pub tables: Vec, + pub annotations: Vec, + pub error: Option, // ← 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: + +```rust +pub struct Diagnostic { + pub code: DiagCode, // Error type code + pub byte_offset: Option, // Location in file + pub object_ref: Option, // 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: + +1. **Info** — Does not affect output validity + - Examples: `XREF_REPAIRED`, `TAGGED_PDF_STRUCT_TREE_DEFERRED` + +2. **Warning** — Output is usable but degraded + - Examples: `STRUCT_INVALID_NAME`, `FONT_GLYPH_UNMAPPED`, `STREAM_DECODE_ERROR` + +3. **Error** — Output for this region/page is invalid; other regions OK + - Examples: `STREAM_BOMB`, `PAGE_OUT_OF_RANGE`, `REMOTE_FETCH_INTERRUPTED` + +4. **Fatal** — Extraction aborted, no usable output + - Examples: `ENCRYPTION_UNSUPPORTED`, `REMOTE_TLS_FAILED`, `REMOTE_DNS_FAILED` + +## Error Flow + +1. **Emission**: During extraction, `Diagnostic` structs are emitted via the `emit!()` macro +2. **Collection**: Diagnostics are collected in `Vec` +3. **Conversion**: Before returning `ExtractionResult`, diagnostics are converted to strings: + ```rust + let diagnostics: Vec = coverage_result + .diagnostics + .iter() + .map(|d| d.message.as_ref().to_string()) + .collect(); + ``` +4. **Exposure**: Final string messages are exposed in `ExtractionMetadata.diagnostics` + +## Key Files + +- `crates/pdftract-core/src/extract.rs` - Main extraction pipeline, defines `ExtractionResult` +- `crates/pdftract-core/src/diagnostics.rs` - Diagnostic system, defines `Diagnostic` and `DiagCode` +- `src/graphics_state/diagnostics.rs` - Legacy diagnostic types (graphics state only) + +## Example Diagnostic + +```rust +// 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 `Diagnostic` struct 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