Calibre library showed zero books
The metadata.db looked healthy, calibre-web still said "no books". The cause was loose EPUB files sitting at the library root.
metadata.db had zero books in it. calibre-web said “No books”. The OPDS feed was empty. Yet ls ~/Desktop/Books showed 37 .epub files sitting right there.
What went wrong
Calibre does not scan a directory. It reads metadata.db, a SQLite index that records every book, its author, and its format. 37 loose EPUB files with no rows in that database are, as far as Calibre is concerned, not books. Both the web UI and the content server were behaving correctly.
The files were missing the Author/Title (id)/Title - Author.epub structure that the index expects:
~/Desktop/Books/
├── metadata.db ← exists, contains 0 rows
├── some-book.epub ← 37 of these
└── another-book.epubThe fix that works
calibredb refuses to touch a library while calibre-server is running, which rules out the obvious command. Add the books through the running server instead:
calibredb --with-library http://127.0.0.1:8090 \
--username kindle --password 'your-password' \
add ~/Desktop/Books/*.epubThat imports each file and reorganises it into author directories. Afterwards, remove the loose duplicates that the import left behind — keep a backup first.
~/Desktop/Books/
├── metadata.db
├── Acharya Prashant/
│ └── Sat Katha - Acharya Prashant.epub
└── ...How to tell it worked
ls ~/Desktop/Books
# metadata.db + author directories only. No loose .epub files.The OPDS “By Title” feed updates immediately. calibre-web picks the same library up because both services mount ~/Desktop/Books, so one import, two interfaces.
The lesson
A Calibre library is the database, not the directory. If the files and the index disagree, the index wins.
Also worth knowing: Jellyfin’s DELETE /Items/{id} deletes the underlying media files. Do not bulk-delete from a library you care about. I learned that one the hard way, which is why this paragraph exists.