Release status — spec differences + test run

kavita-client 0.9.1.4 — built 2026-10-28 10:16:29

This page is generated from kavita_quirks.yaml — the single source of truth for how the release client differs from the published OpenAPI document. 10 fixes patch the spec before code generation; 35 quirks document the server behaviors behind them (28 still open upstream).

Fixes (applied to the release client)

FixTitleEndpointsFields
F1invite response is an object, not a string/api/Account/invite (post)—
F2nullable enum fields—SeriesDto.metadataProviderOverride, ChapterDto.format, MetadataSettingsDto.filterAboveWeight, TachiyomiChapterDto.format
F3bare (non-JSON) string response bodies/api/Health (get), /api/Account/invite-url (get), /api/Upload/upload-by-file (post), /api/Account/opds-url (get), /api/Settings/base-url (get), /api/Metadata/language-title (get), /api/Series/age-rating (get), /api/Account/forgot-password (post)—
F4info.version one step behind the release tag——
F5file-breakdown response is one object, not an array/api/Stats/server/file-breakdown (get)—
F6series-detail-plus nullable object refs/api/Metadata/series-detail-plus (get)SeriesDetailPlusDto.recommendations, SeriesDetailPlusDto.series
F7Annotation/all-for-series response is a list, not one object/api/Annotation/all-for-series (get)—
F8prompt-reread responses may be null/api/Reader/prompt-reread/chapter (get), /api/Reader/prompt-reread/series (get), /api/Reader/prompt-reread/volume (get)—
F9nullable object refs found by the canary—RereadDto.chapterOnContinue, RereadDto.chapterOnReread, SideNavStreamDto.externalSource, SideNavStreamDto.library
F10Stats/device/device-type response is a list, not one object/api/Stats/device/device-type (get)—

Quirk ledger

IdCategoryStatusTitleFix Endpointscovered_byNote
Q01fix-dependentopeninvite returns an object where the spec declares a stringF11tests/integration/test_invite.pyThe three media types all declare {type: string}; the server sends InviteUserResponse. Upstream issue Kareadita/Kavita#4934 covers this class.
Q02fix-dependentopennullable enum fields declared non-nullableF23tests/integration/test_media.py, tests/integration/test_sweep.py, tests/integration/test_small_families.pyEndpoint list covers the curated ops whose responses carry the nullable DTOs; the Schemathesis prototype triage may extend it.
Q03fix-dependentopenbare text bodies where JSON-ish media types are declaredF30tests/integration/test_auth.py, tests/integration/test_invite.py, tests/integration/test_media.py, tests/integration/test_sweep.py, tests/integration/test_email.pyNo exclusion: the raw spec declares text/plain + string schema and the server sends exactly that, so Schemathesis validates fine (the JSON crash was client-side only).
Q05fix-dependentopenfile-breakdown returns an object where the spec declares an arrayF51tests/integration/test_sweep.py
Q06fix-dependentopenseries-detail-plus sends null for non-nullable object refsF61tests/integration/test_metadata_extra.py
Q24fix-dependentopenAnnotation/all-for-series returns a list where the spec declares one objectF71tests/integration/test_metadata_extra.py::test_annotation_all_for_seriesFound by the Schemathesis prototype (2026-09-21): the controller declares ActionResult<AnnotationDto> but returns List<AnnotationDto> (GetAnnotationDtosBySeries).
Q25fix-dependentopenprompt-reread endpoints return null where the spec declares RereadDtoF83tests/integration/test_reader.py::test_prompt_rereadFound by the Schemathesis prototype (2026-09-21): the reread checks return null (no reread due) where the spec declares a non-nullable RereadDto.
Q30fix-dependentopenRereadDto chapter refs are null in real responsesF90tests/integration/test_reader.py::test_prompt_rereadFound by the canary (2026-09-21): the non-null body case carries chapterOnContinue/chapterOnReread as null.
Q31fix-dependentopenStats/device/device-type returns a list where the spec declares one objectF101tests/integration/test_sweep.pyFound by the canary (2026-09-21): the server returns an array of {count, value}; the spec declares a single StringStatCount.
Q32fix-dependentopenStream/sidenav externalSource is nullF91—Found by the canary (2026-09-21): SideNavStreamDto.externalSource is null when no external source is attached; the curated suite does not call sidenav yet.
Q10adead-quirkopenLicense/info returns 204 without a license (spec documents 200)—1—
Q10bdead-quirkopenPlugin/authkey-expires returns 400 (context not in the spec)—1—
Q10cdead-quirkopenUsers/tokens returns 403 (Kavita+ only)—1—
Q15adead-quirkopenSeries/match-info returns 403 (Kavita+ only)—1—
Q18adead-quirkopenLibrary/delete-multiple returns an empty body (spec declares boolean)—1tests/integration/test_mutations.py::test_library_create_and_deleteUpstream issue draft: docs/issue-draft-library-delete-multiple.md.
D01destructiveopenSettings/reset—1tests/integration/test_zz_destructive.py
D02destructiveopenSettings POST (random settings would break the rest of the run)—1tests/integration/test_email.py
D03destructiveopenServer/cleanup—1tests/integration/test_zz_destructive.py
D04destructiveopenUsers/delete-user—1tests/integration/test_mutations.py
D05destructiveopenSeries/delete-multiple—1tests/integration/test_zz_destructive.py
D06destructiveopenChapter DELETE (single)—1—
D07destructiveopenChapter/delete-multiple—1—
D08destructiveopenAccount/register (first-user-only; random bodies 400)—1tests/integration/test_auth.py
Q26undocumented-authopenendpoints requiring auth where the spec documents none—43—401/403 on random apiKeys/ids (or Kavita+ gating); the curated suite covers the subset it exercises with real ids/admin client.
Q27server-error-on-garbageopenserver 500s on garbage input—55—Robustness bugs (not contract drift); candidate for a separate upstream report.
Q28stateful-idopenstateful ops that 4xx/204 on generated ids—321—The fresh server has no entities, so schema-valid but random ids land on undocumented statuses. Re-includable via the value-provider registry (phase 2) against the populated fixture.
Q29aschema-mismatchopendate-time fields carry 7 fractional seconds (.NET ticks)—0—Schema-wide: the server serializes DateTime with 7-digit fractions, but format: date-time (RFC 3339) allows at most 3. Found by the Schemathesis prototype; the runner installs a lenient checker.
Q29bschema-mismatchopenempty date-times serialized as 0001-01-01T00:00:00—0—Schema-wide MinValue leak (DateTime.MinValue instead of null); tolerated by the runner's lenient checker.
Q08resolvedresolveddate-range Stats need a populated library (+ reading-activity year, reading-history tzId)—0tests/integration/test_stats_dates.py
Q15bresolvedresolvedImage library/user covers 404 until a cover is uploaded—0tests/integration/test_image.py
Q15cresolvedresolvedcurrently-reading empty for fresh reads (flipped ReadLast filter)—0tests/integration/test_series_extra.py
Q18bresolvedresolvedLibrary/delete false while a scan task runs—0tests/integration/test_mutations.py
Q19aresolvedresolvedOPDS image feed works headlessly (earlier 400 was a bad-id artifact)—0tests/integration/test_opds.py
Q19bresolvedresolvedOPDS favicon needs an .ico mounted in the container—0tests/integration/test_opds.py
Q23infraresolvedupdate-check endpoints call api.github.com (local TLS mock in fixtures)—4tests/integration/test_sweep.pyMock-pinned via the github_mock fixture; deterministic, so no exclusion.

Release test run

Curated suite (reports/junit-release.xml)

Report from 2026-10-28 10:16:25: 256 passed, 0 xfailed, 0 failed.

On nightly, green means the known upstream bugs are still present — the xfails below are the fix_spec bugs the release client patches. The day one of them starts passing, upstream fixed it and the corresponding fix can be retired.

Known upstream bugs (xfail)

TestReason

Failures

TestMessage

Schemathesis canary (reports/schemathesis-release-junit.xml)

Report from 2026-10-28 10:16:25: 130 passed, 0 xfailed, 0 failed.

On nightly, green means the known upstream bugs are still present — the xfails below are the fix_spec bugs the release client patches. The day one of them starts passing, upstream fixed it and the corresponding fix can be retired.

Known upstream bugs (xfail)

TestReason

Failures

TestMessage

back to index