Skip to content

Conversation

@deluan
Copy link
Member

@deluan deluan commented Nov 15, 2025

Description

Fixes a state synchronization bug where users with a single library or changing library access see no content due to stale selectedLibraries in localStorage/Redux state.

The issue occurs when:

  1. User has selectedLibraries containing library IDs they no longer have access to (e.g., after removing libraries or switching accounts)
  2. The LibrarySelector component doesn't render for single-library users, providing no UI to fix the selection
  3. The stale library IDs persist in state and cause queries to filter for non-existent libraries, resulting in empty album/song lists

Related Issues

Fixes #4553
Fixes #4508
Fixes #4569

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactor
  • Other (please describe):

Checklist

Please review and check all that apply:

  • My code follows the project's coding style
  • I have tested the changes locally
  • I have added or updated documentation as needed
  • I have added tests that prove my fix/feature works (or explain why not)
  • All existing and new tests pass

How to Test

Prerequisites:

  • A Navidrome instance with at least one library containing music

Test Scenario 1: Single library with stale state

  1. Open browser DevTools Console
  2. Run: localStorage.setItem('state', JSON.stringify({library: {userLibraries: [{id: 1, name: "Music Library"}], selectedLibraries: [2]}}))
  3. Refresh the page
  4. Expected: Albums and songs should display correctly (selectedLibraries automatically cleaned)

Test Scenario 2: Switching from multiple to single library

  1. Start with a user having access to multiple libraries
  2. Select one or more libraries using the library selector
  3. Remove all but one library from the user's access (via admin settings)
  4. Refresh the page
  5. Expected: The single library's content should display correctly (no empty state)

Test Scenario 3: Account switching

  1. Login as user A with libraries [1, 2] selected
  2. Logout and login as user B who only has access to library [3]
  3. Expected: User B should see their library content (not empty albums/songs)

Additional Notes

Implementation:

  • libraryReducer.js: Validates selectedLibraries when SET_USER_LIBRARIES is dispatched, filtering out invalid IDs and resetting to empty array for single-library users
  • wrapperDataProvider.js: Adds defensive validation in getSelectedLibraries() to check against current user libraries before applying filters
  • libraryReducer.test.js: Comprehensive test coverage (10 new tests) for all state transition scenarios

Impact:

  • Minimal changes, focused on the specific bug
  • No breaking changes to existing functionality
  • Backward compatible with existing multi-library workflows

@deluan deluan marked this pull request as ready for review November 15, 2025 20:34
Copilot AI review requested due to automatic review settings November 15, 2025 20:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a state synchronization bug where users with a single library or users who lose access to previously selected libraries encounter empty content due to stale selectedLibraries persisting in localStorage/Redux state.

Key Changes:

  • Added validation logic in libraryReducer.js to filter out invalid library IDs from selections and automatically reset selection for single-library users
  • Added defensive validation in wrapperDataProvider.js to validate selected libraries against current user libraries before applying filters
  • Added comprehensive test coverage (10 new tests) covering various state transition scenarios

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
ui/src/reducers/libraryReducer.js Implements core fix by validating selectedLibraries against userLibraries when SET_USER_LIBRARIES is dispatched, filtering invalid IDs and resetting to empty for single-library users
ui/src/dataProvider/wrapperDataProvider.js Adds defensive layer in getSelectedLibraries() to validate selections from localStorage and return empty array for single-library users
ui/src/reducers/libraryReducer.test.js New test file with comprehensive coverage for SET_USER_LIBRARIES, SET_SELECTED_LIBRARIES, and edge cases including stale IDs, single-library transitions, and empty library lists

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Fixes issues where users with a single library see no content when
selectedLibraries in localStorage contains library IDs they no longer
have access to (e.g., after removing libraries or switching accounts).

Changes:
- libraryReducer: Validate selectedLibraries when SET_USER_LIBRARIES
  is dispatched, filtering out invalid IDs and resetting to empty for
  single-library users (empty means 'all accessible libraries')
- wrapperDataProvider: Add defensive validation in getSelectedLibraries
  to check against current user libraries before applying filters
- Add comprehensive test coverage for reducer validation logic

Fixes #4553, #4508, #4569
@deluan deluan force-pushed the fix-library-selection-single-user branch from c3126f7 to f17da06 Compare November 15, 2025 22:36
@deluan deluan merged commit 395a36e into master Nov 15, 2025
20 checks passed
@deluan deluan deleted the fix-library-selection-single-user branch November 15, 2025 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants