diff --git a/web/src/book-detail.ts b/web/src/book-detail.ts index bb35c84f..b1f48d76 100644 --- a/web/src/book-detail.ts +++ b/web/src/book-detail.ts @@ -210,8 +210,20 @@ Alpine.data("bookDetail", () => { headers: { Authorization: getAuthHeader() }, }), ]); - const notes = noteResp.ok ? await noteResp.json() : []; - const highlights = hlResp.ok ? await hlResp.json() : []; + // A partial failure must not read as "no annotations": a failed + // endpoint used to be published as an empty list, silently wiping + // that kind from the banner while the other kind stayed (found + // auditing the app's fetch-wipe fix, bookhoard-app 07bbb4c). + // Keep the previous rows; the next banner open retries. + if (!noteResp.ok || !hlResp.ok) { + console.warn( + `banner annotation load failed ` + + `(notes ${noteResp.status}, highlights ${hlResp.status}) — keeping previous`, + ); + return; + } + const notes = await noteResp.json(); + const highlights = await hlResp.json(); const built = buildAnnotationRows(notes, highlights); this.bannerRows = built.rows; this.bannerSources = built.sources;