Repository navigation
A security and performance audit, a French national library, book ratings, and a long run of library scan, search and cover fixes
This release has two halves. The first is an audit of the API, the database and the downloads path: error messages no longer carry database, filesystem or upstream text, file deletes stay inside your library folders, connections from download clients and the proxy are address checked, finished download rows are trimmed after 90 days, the Wanted list and the download pollers stop reading whole tables, large audiobook downloads no longer stop at two minutes, and the web app's files are cached for a year. Several API statuses changed along the way, and the upgrade notes list every one. The findings are written up in docs/audits/2026-10-bindery-security-errors-performance.md. The second half is features and fixes. The Bibliothèque nationale de France joins as an opt in metadata provider, book ratings show in the UI, you can set a book's cover from an uploaded image or from its own file, fix a single book's series from the book, and use Norwegian and Swedish translations. Add to Library can filter results to books or authors, and the Authors list shows how many of each author's books you have. Much of it came from francisrath and johnistheman, who reported and wrote it: the library scan now leaves torrent, NAS and snapshot folders alone, multi-disc audiobook torrents import again, releases a tracker stores with decomposed accents are found, and covers Bindery stores itself show everywhere. The Go toolchain moves to 1.26.9, which fixes eleven standard library vulnerabilities. Two database migrations (102 and 107) and one rewrite of the stored duplicate keys run on their own at startup. Please read the upgrade notes before updating a long running install.
Upgrade notes
API and behaviour changes from the audit. If you script against the API, run a reverse proxy in front of Bindery, link author folders to another disk, or have run Bindery for a long time, read these first.
- Deleting a book or author with its files refuses paths whose real location is outside every library root (#1640, #3175). Bindery resolves symlinks on both the file and the roots before it deletes. If you link an author folder to another disk (
/books/Author -> /mnt/disk2/Author), add the target (/mnt/disk2, or the folder you link to) as an extra root folder under Settings, Root Folders. Otherwise deleting that book drops its row from Bindery, logspath containment: refusing to delete fileand leaves the files on disk. A library root that is itself a symlink keeps working, and with no root at all every file delete is now refused (a default install always has/books). - Finished download rows older than
BINDERY_DOWNLOAD_RETENTION_DAYS(default 90) are deleted (#3187). A scheduled job removesimportedandfailedrows, in batches, and its first pass runs about six hours after the first start of the new version. On an install that has run a long time that is most of the downloads table, in one go. SetBINDERY_DOWNLOAD_RETENTION_DAYS=0before the first start of the new version if you want to keep them. History, the blocklist and your library are never touched, and live or waiting rows (includingimportFailedandimportBlocked) are kept. Once an imported row is gone Bindery no longer remembers that exact release was grabbed, so if the book becomes wanted again the same release can be grabbed again instead of being refused as already imported. - The Queue page hides
importedrows older than 7 days (#3187). They are on History. Failed and blocked rows stay until you deal with them. GET /api/v1/wanted/missingreturns the{items, total, limit, offset}envelope only when you passlimit(#3187). Withoutlimitit still answers the bare array, so existing scripts are unaffected. The Wanted page now pages and searches on the server.- An oversized JSON body answers
413instead of400(#3176). A body over the 1 MiB limit on the indexer, download client, notification, import list, profile and custom format create and update calls, the genre calls and the manual import calls answers413with{"error": "request body too large"}. An oversized migration upload also answers413. - Unknown API paths answer JSON (#3176). A path that does not exist under
/apior/api/v1answers404with{"error": "not found"}, and a wrong method answers405with{"error": "method not allowed"}and anAllowheader, where they used to be the plain text404 page not foundand an empty405. A crash inside a handler answers{"error": "internal server error", "request_id": "..."}, and the request id is in Settings, Logs. POST /api/v1/prowlarr/{id}/testreturnsokas a JSON boolean (#3176). It used to be the string"true"or"false". Scripts comparing against the string need updating.- Grab and retry errors carry a code and fixed texts (#3174). A grab or retry whose download client refuses the release or cannot be reached answers
502withfailed to send the release to the download client. A missing download client is a400with"code": "no_download_client", and the web app now keys on the code instead of the message text, so a script matching the old message text should match the code. A download client connection test that fails after reaching the client answers502instead of400. A rollback of an unknown Audiobookshelf run answers404and an unavailable one503instead of400, and changing the role of an unknown user answers404. Lookups that failed because the database was unavailable answer500instead of404. - The OIDC providers list is trimmed for anyone who is not an admin, and
/auth/oidc/redirect-baseis admin only (#1640, #3175).GET /api/v1/auth/oidc/providersgives the login page what it needs but returnslast_error,last_attemptandallowed_groupsonly to an admin. Behind a proxy,X-Forwarded-Protomust behttporhttpsandX-Forwarded-Hosta plain host with an optional port before either is used to build the OIDC redirect URL. - Changing your password is rate limited (#3175). The sixth wrong current password in a row answers
429, like the login form. A successful change clears the count. Stored password hashes that ask for more than 256 MiB, 10 passes or 8 threads of argon2 are refused instead of run. - Log lines are written in batches (#3185). After a crash or power loss, up to the newest 250 ms of log rows can be missing from Settings, Logs. A normal shutdown writes everything.
- Migration 107 adds four indexes at startup (#3185). About half a second on a database with 200,000 history rows.
- Large downloads and zips (#3177). A book or audiobook download is no longer cut off at two minutes, only dropped if the client stops reading for five minutes. Audiobook zips store audio, ebook and image files uncompressed, so they build far faster.
Other behaviour changes.
- Umlaut matching is stricter (#3123, #3156). A release naming "Michal" no longer matches the author Michael, and Samuel no longer matches "Samul". Only a real ä, ö or ü is flexible now, so "Müller" still finds Müller, Mueller and Muller releases. The trade off: a name you typed in plain ASCII is taken as typed, so a book by "Mueller" no longer matches a release spelled "Muller", and an ASCII spelled German author no longer matches a release that dropped the vowel. If a release you expect stops matching, search for it by hand.
- Stored duplicate keys are rewritten once on the first start (#3122, #3158). A title filed with its article last (
Trace of Death, A) now has the same key asA Trace of Death. Every book's key is recomputed during the first boot, which took about 1.4 seconds for 100,000 books on a development machine. Rows that now share a key are not merged or removed. They stay as they are and show up together in Review duplicates. - In Library now includes partly owned dual format books (#3132, #3134). A book set to Both that has one format imported is listed under In Library as well as Wanted, and the author page filter and In library count follow the same rule. If you used In Library to mean "every format it wants is here", it now means "at least one file is here".
- A rejected Hardcover token pauses Hardcover for up to an hour (#3101, #3160). When Hardcover refuses the saved API token, Bindery stops asking with it. Saving a new token lifts the pause at once, Test connection still reaches Hardcover, and one probe request an hour lets a restored token recover by itself. Settings shows a notice while the pause is on.
- The library scan skips known junk folders (#3135, #3136, #3155). Torrent client and sync folders (
.torrents,.Trash-*,.incomplete,.AppleDouble,.stfolder), NAS thumbnail, recycle and snapshot folders (@eaDir,#recycle,.@__thumb,.zfs,.snapshots,lost+found), your configured download folders when they sit inside a library folder, and any folder holding a.binderyignorefile are no longer walked. Entries an earlier scan listed from those folders disappear on the next scan. Other folders that start with a dot are still scanned. - Audiobook torrents in their own folder are placed whole from every client (#3139, #3140). From qBittorrent, Deluge and rTorrent a flat multi-file audiobook used to be placed file by file, taking only the audio. It is now placed as a folder, as from Transmission, so cover art,
.nfoand other files in the torrent's folder come along, and in move mode the torrent's folder is removed afterwards. A qBittorrent torrent added without a root folder is still placed file by file. - BnF is opt in and fetches no covers (#3144, #3150). An install that does not select it in Settings, Metadata Profiles never contacts the BnF.
- Database migrations 102 and 107 run automatically at startup: 102 adds the table that remembers which series a book was taken out of (#2554), and 107 adds the four indexes above (#3185). Both are additive and need nothing from you.
Security
- Error responses no longer carry database, filesystem or upstream text (#3174, #3176). Several API endpoints answered a failure with the raw error string, which could include a metadata provider's request URL with its API key and the resolver address, a SQL driver message, a filesystem path from a failed
stat, or whatever page a download client or Prowlarr returned. They now answer with a fixed message and keep the detail in the Bindery log. This covers grab and retry of a queue item (and the per row results of a bulk retry or remove), the book rebind and audiobook enrich calls, the author relink calls, add book and adoption, adding a root folder (which still says whether the path is missing, unreadable or under a file), manual import paths and the Fix Match preview, the user role change, the migration uploads and the Audiobookshelf import and rollback calls. Download client and Prowlarr connection tests still say what went wrong, but only the first line, with credentials redacted, at most 200 characters, and an unreachable client is named with the host and port you configured. A paused metadata provider (daily quota or rejected token) still says so. The visible status changes are in the upgrade notes. - File deletes refuse paths outside every library root, including when no root is configured, and a symlink inside a root that points outside it is no longer deletable (#1640, #3175). The delete check used to accept the path as written and let everything through when no root resolved at all. Both the path and the root are now resolved, a file that is already gone can still be cleaned up, and a path with a
..in it or one that runs through a link that cannot be resolved is refused. The refusal is logged with the path, and the row is still removed. See the upgrade note about linked author folders. - The outbound proxy no longer skips the connect time address check (#3175). With
BINDERY_OUTBOUND_PROXYset, a destination on the bypass list (BINDERY_OUTBOUND_PROXY_BYPASS_LOCALorBINDERY_OUTBOUND_PROXY_NO_PROXY) was dialled directly with no check on the address it resolved to. Cover images, webhooks, Prowlarr and OIDC discovery now check those direct connections too. Your own proxy is still reachable on a LAN or loopback address. - Download clients and Audiobookshelf can no longer redirect Bindery to a link local or cloud metadata address (#3175). Connections to SABnzbd, NZBGet, qBittorrent, Deluge, Transmission, rTorrent and Audiobookshelf are checked when they connect and on every redirect. LAN, loopback and Docker hostnames work as before, and these clients still do not use
BINDERY_OUTBOUND_PROXY. A client saved on a169.254.x.xaddress now fails with a clear "link-local address" error. - Changing your password is rate limited, and stored argon2 settings are capped (#3175). Six wrong current passwords in a row answer
429, so a stolen session cookie cannot be used to guess the password. A stored hash asking for more than 256 MiB, 10 passes or 8 threads is rejected before any work is done, and one with zero passes or threads can no longer crash the login. Hashes written by Bindery are unaffected. - The public OIDC provider list no longer shows discovery errors or group names, and
redirect-baseis admin only (#1640, #3175). Forwarded headers are validated before they are used to build the OIDC redirect URL. - Calibre and Readarr database paths with
?,#or%in them are opened literally (#3175). The path was pasted into the database connection string, so a folder name such aslib ?mode=rwccould change how, and which, file was opened. - Built with Go 1.26.9 (#3131). The binaries and the container image move from Go 1.26.8 to 1.26.9, which fixes eleven standard library vulnerabilities that
govulncheckreports as reachable from Bindery's code: eight innet/http(GO-2026-6603, 6605, 6609, 6610, 6611, 6612, 6613, 6617), one innet/textproto(GO-2026-6608), one incrypto/tls(GO-2026-6607) and one inos(GO-2026-6604). Thanks to francisrath for the bump.
Added
- Bibliothèque nationale de France metadata provider (#3144, #3150). The BnF can be chosen as the primary metadata provider in Settings, Metadata Profiles. Legal deposit puts nearly every book published in France in its catalogue under the French edition title, so a French library whose indexers name releases after the French edition ("Alice au pays des merveilles") gets that title instead of the original English one other providers list. Books carry their language, publisher, year, ISBNs and page count, and the original title of a translation. Translators and illustrators are never taken for the author. It reads only BnF's printed book records, under the Licence Ouverte 2.0, credited in Settings and, with the date each record was retrieved, on every BnF book and author page, and it fetches no covers. It is opt in: an install that does not select it never contacts the BnF, and when selected it sends at most one request a second. Thanks to mnivoliez for the request.
- Set a book's own cover (#3017, #3171). Upload cover (or Change cover) under the cover on a book's page picks an image to use instead. Scripts can do the same through
POST /api/v1/book/{id}/cover, which takes a JPEG, PNG, WebP or GIF image (up to 10 MB) as the request body, answers413over the limit and415for anything else, and returns the book. The image is stored by Bindery itself, like covers taken from files, so it does not depend on a remote host, and it replaces the current cover. Refresh and enrichment only fill an empty cover, so an uploaded one stays. Thanks to francisrath for the request and the change. - Book ratings in the UI (#3124, #3125). The community rating Bindery already stores for each book now shows on the book detail page, in the Books table and grid, in an author's book table and grid, and on book results in Add to Library. The Books table can be sorted by rating, with unrated books last. Hover a rating to see how many ratings it is based on. OpenLibrary search results now carry a rating too. Thanks to johnistheman for the request and the change.
- Books / Authors filter in Add to Library (#3126, #3127). The result list has an All / Books / Authors control. The Add Book button opens on a flat list of books in relevance order and the Add Author button on authors only, so a title search no longer sits under a stack of author rows. Switching views is instant, and each view shows how many results it holds. The work count beside an author now also comes from Hardcover, and is kept when another provider's record for the same author wins the merge. Thanks to johnistheman for the request and the change.
- Books you have, per author, on the Authors list (#3092, #3095). The Books column in the table view reads as have / total, for example 5 / 12, and each card in the grid view says how many of the author's books are in your library. A book counts as in your library once at least one of its files is on disk, the same rule as the Books page and the In library number on the author's page. An author with no books shows a dash. Thanks to johnistheman for the request and the change.
- Sort and more filters on an author's page (#3087, #3088). The book list on an author's page has a Sort control: title ascending or descending, published newest or oldest, and added newest or oldest. It works in grid view and on phones, where the only sort before was a column header that is not shown. The Title column header sorts as well as Published. Two filters join Type, Status and Published: Monitored, and Language, which appears only when the author's books are in more than one language and treats spellings such as
enandengas the same language. Books with no release date now sort last instead of first. Thanks to johnistheman for the request and the change. - Fix a book's series from the book (#2554, #3090). Edit metadata has a Series field, limited to the author's series, with a position and New series… to create one, so a book filed under the wrong series or missing its number can be fixed without going through the series page. No series takes the book out of every series it is in. Admin only. A book taken out of a series is no longer put back by the next refresh: the book page lists the series it was taken out of, with Restore, and Unlock all fields hands the book's series back to refresh. In the Hardcover missing list, Add on a book you took out puts it back in that series, and Fill all still leaves removed books out. Thanks to magrhino for the request and francisrath for the change.
- Covers from your own files (#2980, #3094). A book that no metadata provider has a cover for now takes one from its file: the art embedded in an M4B, MP3, FLAC or EPUB, or a
cover.jpgorfolder.jpgin a multi file audiobook's folder. Books already in the library pick theirs up on the next library scan. A provider's cover is never replaced. Thanks to francisrath for the request and the change. - Norwegian (Bokmål) and Swedish translations (#2985, #2994). The web UI is now available as Norsk bokmål and Svenska, picked automatically from your browser language or chosen under Settings, General. Browsers set to Norwegian Nynorsk or plain Norwegian get Bokmål, and Swedish works for both Sweden and Finland. Thanks to francisrath for offering to proofread the Norwegian.
Changed
- A book no longer takes a translation's cover (#3018, #3093). When no metadata provider had a cover, Bindery looked one up by the ISBN of every edition of the work, translations included, so a book often showed a translated edition's cover with another title, typically the German one. Only editions in the book's own language, or with no language recorded, are used for that lookup now. A book whose only available cover is a translation's keeps no cover, and you can set one yourself. Thanks to francisrath for the report and the fix.
- Author sorting says what it does (#2805, #3116). The Authors list's default sort is labelled Last name A to Z and Z to A, next to the existing First name options, because it always sorted by last name. The merge authors dialog lists authors in that same order instead of by first name, and the Books grid's sort menu offers Author A to Z and Z to A, which only the table's column header reached before. Thanks to francisrath for the change.
- Finished download rows are trimmed, and the Wanted list and the download pollers no longer read everything on every request (#3187). Every grab added a row to the downloads table and nothing removed one, so the Queue page (polled every 5 seconds), the Wanted list and each 15 second download poll got slower the longer an install ran. See the upgrade notes for the retention window and the first pass.
GET /api/v1/wanted/missingpages when you passlimit, and its search now runs on the server. The SABnzbd and NZBGet pollers look their downloads up once per poll instead of once per queue item. - Faster book lookups on big libraries (#3185). Every book query used to build a table of the first file of each format across all book files before it answered, so opening one book cost the same as a whole library scan. Files are now looked up for the books on the page only. On a test library of 20,000 books and 30,000 files, opening a book went from about 54 ms to 0.13 ms, the first page of the Books list from about 66 ms to under 1 ms, and the Wanted list from about 98 ms to 20 ms. A new index makes filtering History by event type instant (the worst case on 200,000 history rows went from about 220 ms to under 0.1 ms), and three smaller indexes cover pending releases per book, the newest first downloads list and the in use check when deleting a quality profile.
- Log writes are batched, and metadata cache eviction no longer scans the whole cache (#3185). The persistent log is written in one transaction per 100 records or 250 ms instead of one write per line, which takes about 8 times less of the database connection's time. A full in memory metadata cache now samples 32 entries to make room instead of scanning every entry under its lock.
- The web app's files are cached for a year (#3177). Build files under
/assets/carry a content hash in their name, so the browser and any proxy in front of Bindery can keep them without asking again. The app shell, favicon and manifest are still checked every time, so an upgrade reaches you straight away. - Audiobook zips build much faster (#3177). Audio, ebook and image files are stored in the zip as they are instead of being compressed a second time. A zip of an 800 MiB audiobook folder went from about 14 seconds of CPU to well under a second. Text, cue sheets and PDF are still compressed.
- Metadata lookups keep more connections open (#3177). Open Library, Hardcover, Google Books and the other metadata providers keep up to 16 idle connections per host instead of 2, so a burst of parallel lookups reuses them instead of reconnecting.
- One JSON error shape across the API (#3176). See the upgrade notes for the
413,404,405,500and Prowlarr test changes. The browser CSRF rejection and the OPDS Basic auth429and503are JSON now, and the CSRF one is labelledapplication/json(it was labelledtext/plain). The new Error format section indocs/API.mdlists every status. - Hardening of the test suite (#1844 and #3130, #1845 and #3117, #1846 and #3129, #1847 and #3128). The lifetime context, search timeout, scheduler and recommender wiring, and outbound proxy transport tests now exercise behaviour instead of comparing pointers, so they fail when the behaviour breaks. Thanks to francisrath.
- Changing the primary metadata provider or the Google Books key now takes effect immediately, no restart (#1771). Picking BnF, DNB, NB, Hardcover or OpenLibrary under Metadata Profiles, or saving a Google Books key under API Keys, used to be stored and then ignored until Bindery restarted, so a book added in between still came in through the old provider. The next lookup now uses the new setting. Lookups already running when you save finish on the provider they started with. Authors already in your library stay linked to the provider they were added from, as before.
Fixed
- The Advanced settings tab no longer lists Bindery's own startup markers as unrecognised keys (#3192). The five
backfill.*_revrows (dedup key, sort keys, book sort key, search key and ASIN case) record which normalizer revision each startup backfill last ran at. They were missing from the settings registry, so the tab labelled them "Unrecognised", said nothing read them, and offered a Remove button. They now show as internal bookkeeping. Removing one is harmless but makes the next start repeat that backfill once, and a new test fails when a backfill marker has no description. - Large audiobook downloads no longer stop at two minutes (#3177). A book or audiobook download was cut off when it had been running for two minutes, however steadily the client was reading, which hit big files on a slow link. Downloads now run as long as the client keeps reading (one that stops for five minutes is dropped), and resuming with a range request still works. The OPDS download and the Calibre bridge file transfer are covered too.
- Recommendations favour the genres you read, not the ones you read least (#3172, #3173). The genre profile behind Discover weighed a genre by how rare it was among your genres rather than among your books, so the genre most of your library is in came out negative: books in it were scored down, and it was left out of the genre-based searches. Weights are now never negative, and your main genres count for recommendations. A genre on nearly every book is still discounted. Thanks to francisrath for the report and the fix.
- Hardcover pauses until its daily quota resets (#2593, #2699). When Hardcover reports no requests left in its daily bucket, Bindery stops sending requests with that token until the reset, keeps the pause across restarts, and shows when the token can be used again in Settings, API Keys. With Hardcover as the primary provider, bulk imports and background catalogue work stop on the hold instead of repeatedly asking an exhausted key. With Hardcover only an enricher, held calls fail at once and ISBN lookups fall through to the other providers. Short per minute throttling is handled as before. Thanks to magrhino for the report and the change.
- Split edition catalogue rows no longer count as missing books you already own (#2524, #2915). Some Hardcover catalogues list a novel's own split into parts editions beside the whole novel (The Way of Kings at position 1, with Part 1 and Part 2 at 1.1 and 1.2). Already owning the whole novel left those parts listed as missing and offered an add button that queued a duplicate download. They now show in their own collapsed section, linked to the book that covers them, and Fill gaps no longer creates them. Thanks to gchahcg for the fix and magrhino for the Stormlight and Wheel of Time catalogue data that shaped the rule.
- Partly owned dual format books stay in In Library (#3132, #3134). A book set to Both that already had one format imported showed under Wanted but vanished from Books, In Library. In Library now lists any book with at least one file on disk, and the book still appears under Wanted while a format is missing. With a format chosen, the book has to own that format. Thanks to SturmB for the report.
- A rejected Hardcover token no longer costs a request per row (#3101, #3160). A bulk import, discovery sweep, catalogue sync, list sync or scheduled refresh stops at the first rejection and says "Hardcover rejected the API token", instead of sending one doomed request for every row. Server errors and queries Hardcover refuses for other reasons do not pause anything. See the upgrade note above.
- A title filed with its article last is the same book as the natural spelling (#3122, #3158). A library row named
Trace of Death, A(the way Calibre files sort titles) and a catalogue entry namedA Trace of Deathproduced two different duplicate keys, so a catalogue sync created a second row for a book you already had.The HobbitandHobbit, The,Der ProzessandProzess, Der, and the same shape for the other articles Review duplicates already knows now key as one title, and the sync and the importers match the row you have. Only a lone article after the last comma counts, soLove, ActuallyandMe, Myself and Iare left alone. See the upgrade note above. - A release naming "Michal" no longer matches the author Michael (#3123, #3156). Release matching let every "ae", "oe" and "ue" in a name be optional, so Michael matched Michal, Samuel matched Samul, and Joel, Noel, Raphael and Manuel had the same problem. Only a real ä, ö or ü is flexible now. See the upgrade note above for what that costs ASCII spelled names.
- Releases a tracker stores with decomposed accents are found (#3137, #3138). Some trackers store a release title decomposed (an
afollowed by a combining ring instead ofå) and match search terms byte for byte, so every search for such a book came back empty, while searching the author alone found it. When a search finds nothing and the title or author has letters that decompose (å, é, ñ, ö and the like, but not ø or æ), Bindery now runs it once more with the decomposed spelling. The relevance check that decides whether an indexer's answer is about the book also reads a decomposed release title as the composed one. Thanks to francisrath for the report and the fix. - Multi-disc audiobook torrents import again (#3139, #3140). A qBittorrent, Deluge or rTorrent download such as
Fjellvinden/Fjellvinden CD1/01 Spor 01.mp3andFjellvinden/Fjellvinden CD2/01 Spor 01.mp3was blocked with "two files in this download would be placed at the same path": the torrent's own folder was taken for the client's shared download folder, so each file was placed by its name alone. The folder is now placed whole with its disc folders, as it already was from Transmission. With multi-disc flattening on, or a per-track file template, the tracks are numbered across discs in disc order. Norwegian and DanishDel 1folders, and folders such asFjellvinden_Cd 01, count as discs too. Blocked downloads import with Retry import. Thanks to francisrath for the report and the fix. - Library Scan leaves torrent folders and other non-library folders alone (#3135, #3136, #3155). A torrent client saving into the library (for example
/data/audiobooks/.torrents, so imports can hardlink and keep seeding) made the scan find every torrent copy again and list it as an unmatched book, one click from importing it or moving it out of the client's folder. The scan, the "already in the library" check and folder import now skip known junk and sync folders, NAS thumbnail, recycle and snapshot folders, the configured download folders when they sit inside a library folder, and any folder holding a.binderyignorefile. Other folders that start with a dot are still scanned, because a book folder can be named that way (...And Then There Were None,.hack Sign). Put a.binderyignorefile in one to skip it. Thanks to francisrath for the report and both fixes. - Covers Bindery stores itself show on the Wanted and Series pages, and a cover that fails to load shows "No cover" (#3146, #3147). The Wanted list and the series endpoints returned stored covers (such as a Calibre library's cover) without routing them through the image proxy, the only way they load, so those rows showed a broken image. The endpoints that answer a change did the same, so saving a book, excluding it, deleting its file, enriching it or adding an author swapped its cover for "No cover" until the page was reloaded. They all hand back the proxied cover now. Every cover in the web app also falls back to the same placeholder as a book with no cover when its image fails to load, instead of the browser's broken-image icon. Thanks to francisrath for the report and the fix.
- A newly added author's page shows that the catalogue is still being fetched (#3058, #3145). Adding an author starts a catalogue sync that can spend minutes fetching a large catalogue, and meanwhile the page said "No books tracked for this author yet" until it was reloaded by hand. It now says the catalogue is being fetched, watches the sync, and shows the books when it ends. The same applies when a Refresh outlasts its one minute wait: the button is freed as before, and the page keeps watching the sync. It pauses in a hidden tab, retries a reload that failed, and stops with the error showing if the author is gone or the server keeps failing. Thanks to francisrath for the report and the fix.
- Dropdowns on phones (#3081, #3082). Dropdowns no longer render oversized on touch screens: they keep the size they were designed at, such as the format picker on Wanted and the Type, Status and Published filters on an author page, and the value still stays clear of the arrow. Text fields are unchanged, so tapping into one still does not zoom the page. The Delete file button on a book page is also a size smaller, to match the row it sits in. Thanks to johnistheman for the report and the fix.
- Dropdown arrows no longer cover the selected value (#3148, #3149). Every dropdown set a compact right padding that left no room for its arrow, so a dropdown as wide as its longest option (Media type showing "Audiobook", Per page showing "50") drew the arrow over the end of it. Dropdowns now keep exactly the room the arrow takes, on desktop as on touch screens, and the Wanted page's Format column is wide enough for the format names in every language. The pager's jump dropdown, meant to read as plain text, no longer draws an arrow at all. Thanks to francisrath for the report and the fix.
- A category you set on an indexer is no longer replaced with 7020 or 3030 (#3169). An indexer whose categories held nothing in the Books (
7xxx) or Audio (3xxx) range, such as a tracker set to8000because it files its books under Other, was searched with the standard ebook or audiobook ID instead of the one you typed, and the search debug showedcategories: 7020. Bindery now searches the8xxxIDs an indexer lists as typed when it lists nothing in the requested media's range. An indexer with no8xxxID keeps the old fallback. Reported by gianfelicevincenzo.