diff --git a/cmd/server/tests/test_helpers_test.go b/cmd/server/tests/test_helpers_test.go index 48eb8adf..656f0b7f 100644 --- a/cmd/server/tests/test_helpers_test.go +++ b/cmd/server/tests/test_helpers_test.go @@ -572,6 +572,10 @@ func setupTestServer(t *testing.T) *TestServerSetup { // the main binary wires database.NewSettingsRegistry(queries) — // the test harness must too or route registration nil-panics. Settings: database.NewSettingsRegistry(queries), + // main.go:246 passes the shared LibraryService here; omitting it + // hands the kobo/kepub CFI converter a typed-nil (kobo markup + // panic-recovered as 500s in TestProgressWeb_KoboIntegration). + LibraryService: libraryService, } router.RegisterRoutes(routerConfig) diff --git a/internal/services/library_service.go b/internal/services/library_service.go index 9746da6f..9bd4cc65 100644 --- a/internal/services/library_service.go +++ b/internal/services/library_service.go @@ -299,6 +299,13 @@ func (s *LibraryService) SyncAllowedExtensions(ctx context.Context) { } func (s *LibraryService) ResolveMediaPath(ctx context.Context, libraryID pgtype.UUID, relativePath string) (string, error) { + // Typed-nil interface guard: a nil *LibraryService held in an + // interface passes `!= nil` checks at call sites; degrade instead + // of panicking (kobo markup 500s were exactly this path). + if s == nil || s.db == nil { + return "", fmt.Errorf("library service not configured") + } + // Get library folders for this library folders, err := s.db.GetLibraryFolders(ctx, libraryID) if err != nil || len(folders) == 0 {