Fix players/get_by_name not always returning a result (#2945)
authorOzGav <gavnosp@hotmail.com>
Mon, 2 Feb 2026 09:23:33 +0000 (20:23 +1100)
committerGitHub <noreply@github.com>
Mon, 2 Feb 2026 09:23:33 +0000 (10:23 +0100)
commit1185e77e2d9c72d0cd5b21d0561f245cd857b4a9
treef8520f9a4ae041e3106ac07c9646d055284786ee
parent1c1e0edc28c35df3490656494314d48a95790c8d
Fix players/get_by_name not always returning a result (#2945)

* fix: Improve player name matching in get_by_name API

The players/get_by_name API was failing to find some players because it only
performed exact matching on the player's name property. This commit enhances
the matching logic to:

- Match against both player.name and player.display_name (which may differ
  if users have customized the player name in config)
- First attempt exact match (case-sensitive)
- Fall back to case-insensitive, whitespace-trimmed matching if exact match fails

This fixes the issue where players like "Alfresco", "Sonos Roaming", and
"pCP-Airplay Test" were returning NULL from the API despite being available
in the players/all endpoint.

* Improve duplicate player name handling in get_by_name

Enhances the get_player_by_name method to handle the edge case where
multiple players might have the same display_name:

- Collects all matching players instead of returning first match immediately
- Logs a warning when multiple players match the same name, including
  the player_ids of all matches
- Guides users to use player_id for unambiguous lookups
- Maintains backward compatibility by returning the first match

This improves debuggability when users have players with duplicate names
(e.g., multiple identical devices with default names or custom config
that creates name collisions).

* Clarify warning message for duplicate player names

Improves the warning message when multiple players match the same name:
- Now shows which player_id was actually returned (first match)
- Explicitly mentions "players/get API" instead of vague "use player_id"
- Makes it clear users should use a different API endpoint for
  unambiguous lookups, not try to pass player_id to get_by_name

This addresses confusion about how to resolve duplicate name lookups.

* Include API endpoint name in duplicate player warning

Prefixes the warning message with "players/get_by_name:" to make it
immediately clear which API call triggered the warning. This helps users
debug their automations and integrations when they see the warning in logs.

Warning now reads:
"players/get_by_name: Multiple players found with name 'X': [...] -
returning first match (Y). Consider using the players/get API..."

* Simplify to single-pass case-insensitive matching

Removes the two-pass approach (exact match first, then case-insensitive)
in favor of a simpler single-pass case-insensitive search.

Benefits:
- Single iteration through players (better performance)
- Simpler, more readable code
- More predictable behavior (always case-insensitive)
- Still handles all real-world use cases

The two-pass approach was protecting against the extremely unlikely
scenario of having players "Kitchen" and "kitchen" simultaneously,
which would generate a duplicate warning anyway.

* Remove redundant text from docstring return statement

* Fix line length to comply with E501 linting rule

* Use player.state.name for matching instead of multiple properties

Simplifies the matching logic to check only player.state.name instead of
checking both player.name and player.display_name. The state.name already
contains the final player name as visible in clients and the API, making
it the single source of truth for player name matching.

As suggested by head dev review.

---------

Co-authored-by: Claude <noreply@anthropic.com>
music_assistant/controllers/players/player_controller.py