How-to guides/PDF/A & Archiving

Fix common PDF/A validation errors in Rust

Auto-repair the most frequent PDF/A conformance problems: missing output intent, unembedded fonts, transparency, and missing XMP metadata.

rust
use pdfluent::{Document, pdfa::{PdfALevel, PdfAFixOptions}};

fn main() -> pdfluent::Result<()> {
    let mut doc = Document::open("noncompliant.pdf")?;

    let opts = PdfAFixOptions::for_level(PdfALevel::A2b)
        .embed_missing_fonts(true)
        .flatten_transparency(true)
        .add_xmp_metadata(true);

    let report = doc.fix_pdf_a_errors(opts)?;
    println!("Fixed {} issue(s)", report.fixed_count());

    doc.save("fixed.pdf")?;
    Ok(())
}
Install:cargo add pdfluentDownload SDK →

Step by step

1

Validate first to understand the errors

Run validate_pdf_a() before fixing to get a baseline list of issues.

rust
let doc = Document::open("noncompliant.pdf")?;
let before = doc.validate_pdf_a()?;
println!("Errors before: {}", before.error_count());
for e in before.errors() {
    println!("  [{}] {}", e.rule_id(), e.message());
}
2

Build fix options

PdfAFixOptions controls which repairs are attempted. Each fix is opt-in to avoid unintended side effects.

rust
use pdfluent::pdfa::{PdfALevel, PdfAFixOptions};

let opts = PdfAFixOptions::for_level(PdfALevel::A2b)
    .embed_missing_fonts(true)
    .flatten_transparency(true)
    .add_xmp_metadata(true)
    .add_output_intent_if_missing(true)
    .remove_javascript(true)
    .remove_embedded_files(false); // keep attachments for PDF/A-3
3

Apply the repairs

fix_pdf_a_errors returns a FixReport listing what was changed. Inspect it to confirm each fix was applied.

rust
let mut doc = Document::open("noncompliant.pdf")?;
let report = doc.fix_pdf_a_errors(opts)?;

for fix in report.applied_fixes() {
    println!("Fixed: {}", fix.description());
}
for skipped in report.skipped_fixes() {
    println!("Skipped (manual): {}", skipped.description());
}
4

Re-validate after fixing

Confirm no errors remain. Some issues (e.g. non-embeddable fonts) require manual intervention.

rust
let after = doc.validate_pdf_a()?;
if after.is_conformant() {
    println!("Document is now PDF/A-2b conformant.");
} else {
    println!("Remaining errors: {}", after.error_count());
}
5

Save the repaired document

Write the fixed file. The output is a full save, not an incremental update.

rust
doc.save("fixed_a2b.pdf")?;

Notes and tips

  • Flattening transparency is a destructive operation. It may change the visual appearance of pages with transparency blending modes.
  • Fonts with embedding restrictions (fsType = 2) cannot be embedded. These cases are reported as skipped fixes and require replacing the font.
  • Removing JavaScript is required for PDF/A-1. JavaScript actions are also prohibited in PDF/A-2 and PDF/A-3.
  • If the document has an existing output intent with a non-ICC color space, the fixer replaces it with sRGB by default.

Why PDFluent for this

Pure Rust

No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.

Memory safe

Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.

Runs anywhere

Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.

Frequently asked questions