fix(api): leere Listen als [] statt null -- Kalender blieb weiss

Ein Konto ohne Kalender bekam auf GET /api/v1/calendars die Antwort
`null`, und die Ansicht brach ab:

    for (const cal of calendars)   ->  "e is not iterable"

Nicht der Kalender ist schuld, sondern eine Eigenheit, die jeden
Listenendpunkt betrifft: In Go ist eine Liste ohne Eintraege oft nil,
und encoding/json schreibt dafuer null statt []. Jede Store-Funktion,
die mit `var out []T` anfaengt, liefert das bei leerem Ergebnis --
Favoriten, Papierkorb, Versionen, Freigaben, Etiketten. Der Kalender war
nur der, der daran zerbricht.

Deshalb die Regel dort, wo alle Antworten durchlaufen: response.JSON
macht aus einer nil-Liste eine leere. Einzelne Objekte und nil bleiben
unberuehrt. In den Stores waere es die falsche Stelle -- es gibt
Dutzende Listenendpunkte, und der naechste faengt wieder mit
`var out []T` an. Eine Regel, an die man sich erinnern muss, ist keine.

Dazu zwei Dinge, die derselbe Fall ans Licht brachte:

  - Der Web-Weg legte, anders als CalDAV, keinen Standardkalender an.
    Ein neues Konto stand vor einer leeren Ansicht und musste erraten,
    dass es selbst einen anlegen soll -- waehrend ein CalDAV-Client, der
    sich vorher verbunden hatte, bereits einen sah, den die Oberflaeche
    nicht zeigte.
  - Die Ansicht faengt eine unerwartete Antwort jetzt selbst ab (?? []).
    Der Server schickt kein null mehr; eine Seite sollte daran trotzdem
    nicht zerbrechen.

Drei Tests in pkg/response: leere Liste wird [], befuellte bleibt
unveraendert, Objekte und nil bleiben, was sie sind.

Zur Korrektur meiner frueheren Erklaerung: Die fehlenden Cache-Header
waren ein echtes Problem, aber nicht die Ursache dieses Fehlers. Der
gemeldete Bundle-Name stimmte diesmal mit dem ausgelieferten ueberein --
daran war zu sehen, dass es kein alter Stand sein konnte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-09-07 19:56:54 +02:00
1 parent 55dcf517f2
commit fbaf24bdbd
4 files changed
+107 -2

No files matched your search

+4 -1
View File
@@ -147,7 +147,10 @@ export default function CalendarPage() {
const loadCalendars = useCallback(async () => {
setError(null)
try {
setCalendars(await calendarApi.list())
// ?? []: Eine Liste, die als null ankommt, legte die ganze Seite lahm
// (das ist einmal passiert). Der Server schickt das nicht mehr – aber
// eine Ansicht sollte an einer unerwarteten Antwort nicht zerbrechen.
setCalendars(await calendarApi.list() ?? [])
} catch (e) {
setError(e instanceof APIError ? e.message : 'Laden fehlgeschlagen')
} finally {