Repository navigation
Description
Summary
bookId is a Fletcher-16 checksum of the lower-cased book title (id: hash(title) in src/scraper/scrapeBooks.ts, src/utils/hash.ts). With only 16 bits, different books end up with the same bookId once a library reaches a few hundred books.
Sync looks up the note by bookId alone (getKindleFile in src/fileManager/index.ts), so when two books collide, the metadata and highlights of one book are written into the other book's note.
Environment
- Plugin: 2.3.1 (plus a local fix for the Amazon login)
- Obsidian: 1.15.0
- OS: macOS
- Amazon region: amazon.co.jp (Japan)
- Library size: about 730 books
What happened
- The
kindle-*frontmatter of one note (title, asin, bookId, ...) was overwritten with another book's values. - Highlights of the other book were added to that note (up to 108 lines).
- 2 pairs of books out of about 730 were confirmed to share a
bookId(reproduced below), and a third pair was observed during sync. (If the checksum were uniform, about 4 pairs would be expected, so this is not a rare accident.)
Colliding books
Titles are shown exactly as they appear in the Kindle notebook on amazon.co.jp. They are not translated, because bookId is computed from the exact string.
| bookId | Book A | Book B |
|---|---|---|
| 6714 | Maps & Civilization: Cartography in Culture and Society (English Edition) | 脳がわかれば心がわかるか──脳科学リテラシー養成講座 |
| 33774 | 知的生産の技術 (岩波新書) | 難解な本を読む技術 (光文社新書) |
How to reproduce the collision
Same computation as the plugin's hash(), in Node.js:
const fletcher16 = require('fletcher');
const hash = (s) => fletcher16(Buffer.from(s.toLowerCase())).toString();
hash('Maps & Civilization: Cartography in Culture and Society (English Edition)'); // '6714'
hash('脳がわかれば心がわかるか──脳科学リテラシー養成講座'); // '6714'
hash('知的生産の技術 (岩波新書)'); // '33774'
hash('難解な本を読む技術 (光文社新書)'); // '33774'Cause
- The hash has only 16 bits, so collisions are expected in libraries of this size.
- Matching uses
bookIdonly, so two books with the same value cannot be told apart. - If a book's title changes on Amazon, its
bookIdchanges too, and the existing note is no longer found. This may also explain duplicate notes (possibly related to [BUG] Flooded with duplicate entries #334 and [BUG] Book title differs from MyClippings.txt and cloud sync, creating duplicate notes #315; I have not confirmed that).
Suggested fix
- Match books by ASIN, and fall back to
bookIdonly when an ASIN is missing:getKindleFileinsrc/fileManager/index.tsisEqualinsrc/sync/syncManager/diffBooks.tsresyncBookinsrc/sync/syncAmazon/index.ts
- Stop writing
kindle-bookId, and treat a note that has onlykindle-asinas a synced note. - Add a test with two books that share a
bookIdbut have different ASINs.
In my fork, this change synced all ~730 books without the colliding books mixing again. I can open a PR if that would be useful.
Notes
The Amazon login problem (#337, #339) is a separate issue, which PR #338 addresses.
Activity