Pre-flight
Current behaviour
The Books page shows "No books in your library yet" despite books existing in the database. All book list API calls fail immediately with a scan error. Authors page shows authors correctly; the failure is isolated to book queries.
Expected behaviour
Books page displays all books. Book list API calls return results.
Steps to reproduce
- Import a Calibre library into Bindery via the Calibre Bridge.
- Navigate to the Books page — it shows empty.
- Confirm books exist in the DB: sqlite3 bindery.db "SELECT COUNT(*) FROM books;" returns a non-zero count.
- Call the book list API directly:
curl -s "http://localhost:8787/api/v1/book?page=1&pageSize=10" -H "X-Api-Key: <key>"
Root Cause
Calibre stores pubdate as 2006-01-02 15:04:05+00:00. When Bindery reads this and writes it to its own SQLite DB, Go serializes the time.Time value using its default time.String() format — 2006-01-02 15:04:05 +0000 UTC — rather than RFC3339. The modernc.org/sqlite driver cannot scan this format back into *time.Time, causing every book list query to fail with the error above.
Workaround
Run the following SQL against bindery.db while the container is stopped:
UPDATE books SET release_date = replace(replace(release_date, ' +0000 UTC', 'Z'), ' ', 'T') WHERE release_date LIKE '% +0000 UTC';
UPDATE books SET last_metadata_refresh_at = replace(replace(last_metadata_refresh_at, ' +0000 UTC', 'Z'), ' ', 'T') WHERE last_metadata_refresh_at LIKE '% +0000 UTC';
UPDATE books SET created_at = replace(replace(created_at, ' +0000 UTC', 'Z'), ' ', 'T') WHERE created_at LIKE '% +0000 UTC';
UPDATE books SET updated_at = replace(replace(updated_at, ' +0000 UTC', 'Z'), ' ', 'T') WHERE updated_at LIKE '% +0000 UTC';
Suggested Fix
Two changes to internal/db/books.go:
- Write side — wrap *time.Time parameters in a helper that formats them as RFC3339Nano before passing to the driver, preventing the bad format from being written going forward.
- Read side — scan all four time columns (release_date, last_metadata_refresh_at, created_at, updated_at) into sql.NullString and parse with a multi-layout fallback covering both RFC3339 and the legacy Go format. This makes existing databases with legacy date formats readable without requiring a migration.
Trace logs
{"error":"scan book: sql: Scan error on column index 8, name \"release_date\": unsupported Scan, storing driver.Value type string into type *time.Time"}
Deployment method
Docker (ghcr.io)
Bindery version
1.15.3
Environment details
- OS: Unraid 7.2.7, kernel x86_64
- Architecture: linux/amd64 (Intel i5-12600K)
- Bindery version: sha-9560eba (via ghcr.io/vavallee/bindery:latest)
- Deployment: Docker Compose
- Calibre version: lscr.io/linuxserver/calibre:latest (KasmVNC-based)
- Calibre library size: ~15,000 books, ~1,378 authors
- Download clients: SABnzbd, qBittorrent (via VPN)
- Indexers: NZBgeek, Nzb.life, altHUB (NZB); LimeTorrents, YTS, 1337x, EZTV, Nyaa.si, The Pirate Bay (torrent) — via Prowlarr
- Reverse proxy: Nginx Proxy Manager
- Calibre integration method: Bindery Bridge plugin running inside calibre-desktop container, port 8484
Pre-flight
Current behaviour
The Books page shows "No books in your library yet" despite books existing in the database. All book list API calls fail immediately with a scan error. Authors page shows authors correctly; the failure is isolated to book queries.
Expected behaviour
Books page displays all books. Book list API calls return results.
Steps to reproduce
curl -s "http://localhost:8787/api/v1/book?page=1&pageSize=10" -H "X-Api-Key: <key>"Root Cause
Calibre stores pubdate as 2006-01-02 15:04:05+00:00. When Bindery reads this and writes it to its own SQLite DB, Go serializes the time.Time value using its default time.String() format — 2006-01-02 15:04:05 +0000 UTC — rather than RFC3339. The modernc.org/sqlite driver cannot scan this format back into *time.Time, causing every book list query to fail with the error above.
Workaround
Run the following SQL against bindery.db while the container is stopped:
Suggested Fix
Two changes to internal/db/books.go:
Trace logs
Deployment method
Docker (ghcr.io)
Bindery version
1.15.3
Environment details