A focused, single-binary repair pipeline that fixes the exact defects that make Google Play Books reject an EPUB with a "processing error" — validated end-to-end on real-world rejected books.
-
⚡ Single Dependency-Free Binary:
- Compiles to one
epub-fixer(.exe)— no runtime, no installer, no DLL hell. - SHA-256 and CRC-32 implemented in-tree to keep the dependency tree minimal.
- Release profile built with LTO for a compact, fast executable.
- Compiles to one
-
🛡️ Non-Destructive by Design:
- Originals are never modified — every repair writes to
<name>-fixed.epub. - Healthy books are detected and skipped with an explicit "nothing to do".
- ZIP integrity is re-verified after every write; input/output hashes are printed.
- Originals are never modified — every repair writes to
-
🧠 Spec-Compliant Container Writer:
- The first zip entry (
mimetype) is emitted STORED and uncompressed, exactly as the EPUB OCF spec demands — a detail many packers (including .NET'sZipArchive) get wrong, silently producing files that fail validation. - All other entries are deflate-compressed with correct CRC-32.
- The first zip entry (
-
🔬 Forensics-Driven Repair Set:
- Every fix below was isolated via delta-testing on books Google actually rejected, then confirmed fixed by EPUBCheck + successful upload. Nothing speculative.
| Repair | Defect Fixed | Why It Breaks Google |
|---|---|---|
| 🛡️ DRM Watermark Stripper | <meta name="Adept.resource" .../> leftovers from ACSM/Kindle→EPUB conversions |
Invalid XHTML attribute (value) breaks the document model across every content file |
| 🔖 TOC Anchor Filler | Empty anchors <a href="..."></a> in the nav document |
EPUB 3 requires text inside nav anchors |
| 🌲 Empty List Pruner | Nested <ol></ol> blocks with no children |
EPUB 3 requires at least one <li> per list |
| ♿ ARIA Role Sanitizer | role="presentation" on anchors |
ARIA forbids this role on <a>; breaks strict parsers |
| 🖼️ SVG Resource Flag | SVGs referencing remote resources without OPF declaration | Missing remote-resources property fails conformance (OPF-014) |
| 🔗 Insecure URL Scrubber | url(http://...) font refs inside SVGs |
Plaintext remote references are rejected outright (RSC-008) |
| 🆔 Identifier Regenerator | Non-UUID unique-identifiers | Google matches the catalog record through this field; a malformed value kills metadata processing before any content is read |
| 🌐 Language Fixer (opt-in) | Wrong <dc:language> |
Affects cataloging; pass --language pt to enable |
cargo build --release
# binary at target/release/epub-fixer(.exe)# one book
epub-fixer book.epub
# a whole folder
epub-fixer ./booksSend the generated <name>-fixed.epub to Google Play Books.
Originals are never modified; output is written as <name>-fixed.epub.
epub-fixer <file.epub | directory> [--out-dir DIR] [--language CODE]
| Argument | Type | Default | Description |
|---|---|---|---|
<path> |
path | (required) | A single .epub file or a directory of .epub files. |
--out-dir <DIR> |
path | input folder | Where repaired files are written. |
--language <CODE> |
string | (disabled) | Rewrites <dc:language> with the given ISO code (e.g. pt). |
Every run prints a per-book action log plus the SHA-256 of input and output.
All repairs were derived from forensic analysis of two books Google kept rejecting, with delta-testing to prove causality:
| Case | Before | After |
|---|---|---|
| Case A — DRM-stripped anthology | 79 EPUBCheck errors → rejected | 0 / 0 — accepted by Google |
| Case B — technical book with SVG diagrams | 3,471 errors + 10 warnings | 0 errors / 21 informational warnings |
| Healthy control #1 | clean | correctly untouched |
| Healthy control #2 | 18 cosmetic CSS errors (accepted anyway) | correctly untouched |
The unit-test suite guards against regressions: healthy books must no-op, valid UUIDs and https:// URLs must survive untouched, sibling identifiers (ISBN etc.) must persist through regeneration, and properties are never duplicated.
epub-fixer-rs/
├── .gitignore # Blocks *.epub and target/ — never commit ebooks
├── Cargo.toml # Dependencies & release profile (LTO)
├── Cargo.lock # Pinned dependency graph
├── LICENSE # MIT License
├── README.md # This documentation
└── src/
└── main.rs # Tool implementation + #[cfg(test)] test module
| Crate | Purpose |
|---|---|
zip |
EPUB container read/write (emits spec-compliant STORED mimetype) |
regex |
Text-level repair patterns |
uuid |
UUID v4 generation for identifier repair |
anyhow |
Ergonomic error handling |
SHA-256 and CRC-32 are implemented in-tree to keep the dependency tree small.
This project is open-source and licensed under the MIT License.