Troubleshooting MusicAssistant And LMS API Issues After Update To 2.6.0

by StackCamp Team 72 views

Hey guys,

If you're like me and recently updated MusicAssistant to version 2.6.0, you might be experiencing some frustrating API issues, especially when using it with LMS (Logitech Media Server). It seems like a number of API calls are failing, leading to music not playing correctly and other hiccups. I’ve been digging into this, and I wanted to share what I've found, along with some potential troubleshooting steps.

I even tested it out using the Navidrome demo server, and everything worked smoothly there, which points to a possible issue with the LMS API implementation in MusicAssistant. Let’s dive into the specifics and see if we can get this sorted out!

Identifying the Problem: Common Error Logs

To get a clearer picture of what’s going on, let’s look at some of the error logs I’ve gathered. These logs provide valuable clues about where the problems might lie. Remember, detailed error messages are your best friends when troubleshooting. Analyzing them carefully can save you a lot of time and frustration.

The most common issue appears to be related to missing fields and data structure mismatches, particularly with the Child instance and playlist entries. These errors suggest that the data being returned by the LMS API isn't quite what MusicAssistant expects, leading to parsing failures and functionality breakdowns.

Generic Error Log: Missing "is_dir" Field

One of the most frequent errors I encountered is the "MissingField: Field 'is_dir' of type bool is missing in Child instance" error. This pops up in various scenarios, such as when MusicAssistant tries to update metadata for an artist.

2025-09-28 16:30:25.706 ERROR (MainThread) [music_assistant.metadata] Error while updating metadata for library://artist/8757: Field "is_dir" of type bool is missing in Child instance
Traceback (most recent call last):
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/metadata.py", line 755, in _process_metadata_lookup_jobs
    await self.update_metadata(item)
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/metadata.py", line 273, in update_metadata
    await self._update_artist_metadata(item, force_refresh=force_refresh)
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/metadata.py", line 489, in _update_artist_metadata
    if mbid := await self._get_artist_mbid(artist):
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/metadata.py", line 711, in _get_artist_mbid
    ref_tracks = await self.mass.music.artists.tracks(
        artist.item_id, artist.provider, in_library_only=False
    )
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/media/artists.py", line 120, in tracks
    provider_tracks = await self.get_provider_artist_toptracks(
        provider_mapping.item_id, provider_mapping.provider_instance
    )
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/media/artists.py", line 229, in get_provider_artist_toptracks
    items = await prov.get_artist_toptracks(item_id)
  File "/app/venv/lib/python3.13/site-packages/music_assistant/providers/opensubsonic/sonic_provider.py", line 533, in get_artist_toptracks
    songs: list[SonicSong] = await self._run_async(self.conn.get_top_songs, sonic_artist.name)
  File "/app/venv/lib/python3.13/site-packages/music_assistant/providers/opensubsonic/sonic_provider.py", line 197, in _run_async
    return await asyncio.to_thread(call, *args, **kwargs)
  File "/usr/local/lib/python3.13/asyncio/threads.py", line 25, in to_thread
    return await loop.run_in_executor(None, func_call)
  File "/usr/local/lib/python3.13/concurrent/futures/thread.py", line 59, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/app/venv/lib/python3.13/site-packages/libopensonic/connection.py", line 1574, in get_top_songs
    return [Child.from_dict(entry) for entry in dres['topSongs']['song']]
  File "<string>", line 4, in __mashumaro_from_dict__
  File "<string>", line 14, in __mashumaro_from_dict__
mashumaro.exceptions.MissingField: Field "is_dir" of type bool is missing in Child instance

In simpler terms, this error means that MusicAssistant is expecting a field called is_dir (which should be a boolean value indicating whether an item is a directory) in the data it receives from the LMS API. However, this field is missing in the Child instance, causing the process to fail. This is crucial for metadata updates because MusicAssistant uses this information to correctly categorize and display your music library.

This issue specifically affects the get_top_songs method within the libopensonic library, which MusicAssistant uses to interact with Subsonic-compatible servers like LMS. When MusicAssistant requests the top songs for an artist, it expects the API response to include the is_dir field for each song. The absence of this field leads to a mashumaro.exceptions.MissingField error, halting the metadata update process. This can prevent MusicAssistant from correctly displaying artist information and top tracks, impacting the overall user experience.

To resolve this, we need to ensure that the LMS API provides the is_dir field in its responses. This might involve updating the LMS server, adjusting MusicAssistant's configuration, or, in some cases, patching the libopensonic library to handle the missing field gracefully. More on potential solutions later!

Error Log When Opening Playlists: Invalid "entry" Field

Another common error crops up when trying to open playlists. Here’s what the log looks like:

2025-09-28 16:32:29.175 ERROR (MainThread) [music_assistant.webserver] Error handling message: CommandMessage(message_id=14, command='music/playlists/playlist_tracks', args={'item_id': '6', 'provider_instance_id_or_domain': 'library', 'force_refresh': False})
Traceback (most recent call last):
  File "<string>", line 86, in __mashumaro_from_dict__
  File "<string>", line 14, in __mashumaro_from_dict__
mashumaro.exceptions.MissingField: Field "is_dir" of type bool is missing in Child instance
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/webserver.py", line 386, in _run_handler
    async for item in iterator:
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/webserver.py", line 245, in _iter_items
    async for item in self._json_pipeline(msg):
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/webserver.py", line 308, in _json_pipeline
    result = await handler(**msg.args)
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/media/playlists.py", line 81, in playlist_tracks
    async for item in self.tracks(
        item_id=item_id, provider_instance_id_or_domain=provider_instance_id_or_domain, force_refresh=force_refresh
    ):
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/media/playlists.py", line 69, in tracks
    tracks = await self._get_provider_playlist_tracks(
        item_id, provider_instance_id_or_domain, force_refresh=force_refresh
    )
  File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/media/playlists.py", line 399, in _get_provider_playlist_tracks
    items = await provider.get_playlist_tracks(item_id, page=page)
  File "/app/venv/lib/python3.13/site-packages/music_assistant/providers/opensubsonic/sonic_provider.py", line 500, in get_playlist_tracks
    sonic_playlist: SonicPlaylist = await self._run_async(
        self.conn.get_playlist, prov_playlist_id
    )
  File "/app/venv/lib/python3.13/site-packages/music_assistant/providers/opensubsonic/sonic_provider.py", line 197, in _run_async
    return await asyncio.to_thread(call, *args, **kwargs)
  File "/usr/local/lib/python3.13/asyncio/threads.py", line 25, in to_thread
    return await loop.run_in_executor(None, func_call)
  File "/usr/local/lib/python3.13/concurrent/futures/thread.py", line 59, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/app/venv/lib/python3.13/site-packages/libopensonic/connection.py", line 1253, in get_playlist
    return Playlist.from_dict(dres['playlist'])
  File "<string>", line 88, in __mashumaro_from_dict__
mashumaro.exceptions.InvalidFieldValue: Field "entry" of type Optional[list[Child]] in Playlist has invalid value

What’s happening here? When MusicAssistant tries to load the tracks in a playlist, it calls the get_playlist_tracks method. This method fetches the playlist data from the LMS server. The error log shows that there’s an “InvalidFieldValue” for the “entry” field within the Playlist object. This indicates that the format or content of the playlist entry data from LMS isn't compatible with what MusicAssistant expects. The system is expecting a list of Child objects but receiving something else, leading to the parsing error.

The root cause lies in how MusicAssistant and the underlying libopensonic library handle the playlist structure returned by the LMS server. The Playlist object is defined with a field called entry, which should contain a list of Child objects representing the tracks in the playlist. When the data received doesn’t conform to this structure (e.g., it’s missing fields, has incorrect data types, or is in a different format), the mashumaro library throws an InvalidFieldValue exception. This can be due to changes in the LMS API response format, a bug in MusicAssistant’s playlist parsing logic, or inconsistencies in the data stored on the LMS server itself.

Error Log When Clicking on an Album: Missing "is_dir" in Recommendations

Yet another issue arises when attempting to view album details, specifically when MusicAssistant tries to fetch recommendations. The error log looks like this:

2025-09-28 16:37:33.191 WARNING (MainThread) [music_assistant.music] Error while fetching recommendations from OpenSubsonic Media Server Library: unhandled errors in a TaskGroup (1 sub-exception)
  + Exception Group Traceback (most recent call last):
  |   File "/app/venv/lib/python3.13/site-packages/music_assistant/controllers/music.py", line 1222, in _get_provider_recommendations
  |     return await provider.recommendations()
  |   File "/app/venv/lib/python3.13/site-packages/music_assistant/providers/opensubsonic/sonic_provider.py", line 868, in recommendations
  |     async with TaskGroup() as grp:
  |   File "/usr/local/lib/python3.13/asyncio/taskgroups.py", line 71, in __aexit__
  |     return await self._aexit(et, exc)
  |   File "/usr/local/lib/python3.13/asyncio/taskgroups.py", line 173, in _aexit
  |     raise BaseExceptionGroup(
  | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "<string>", line 23, in __mashumaro_from_dict__
    |   File "<string>", line 14, in __mashumaro_from_dict__
    | mashumaro.exceptions.MissingField: Field "is_dir" of type bool is missing in Child instance

This error is closely related to the first one we discussed, the missing “is_dir” field. The traceback indicates that the issue occurs when MusicAssistant attempts to fetch recommendations from the OpenSubsonic Media Server Library. The same mashumaro.exceptions.MissingField error points to a data structure mismatch between what MusicAssistant expects and what the LMS API provides.

The underlying problem here is that the recommendation fetching process relies on the same data structures as other parts of MusicAssistant, specifically the Child instance. When the LMS API response for recommendations doesn't include the is_dir field, the parsing fails. This highlights a systemic issue where a single missing field can disrupt multiple functionalities within MusicAssistant.

Potential Solutions and Workarounds

Okay, so we’ve identified the problems – now let’s talk about fixing them! Here are a few potential solutions and workarounds you can try:

  1. Verify LMS Version and Configuration:

    • Ensure Compatibility: Double-check that your LMS version is compatible with MusicAssistant 2.6.0. Sometimes, older versions might have API differences that cause these issues. Check the MusicAssistant documentation or community forums for compatibility information.
    • API Settings: Review your LMS settings to ensure that the API is correctly configured and that all necessary endpoints are enabled. In some cases, specific API features might need to be explicitly enabled for MusicAssistant to function correctly.
  2. Update libopensonic:

    • Check for Updates: The libopensonic library is responsible for handling the communication between MusicAssistant and Subsonic-compatible servers like LMS. Check if there's a newer version of libopensonic available. A newer version might include bug fixes or compatibility updates that address the missing is_dir field issue.
    • Manual Update: If a newer version isn't automatically installed, you might need to manually update libopensonic. This usually involves using pip or a similar package manager to install the latest version from PyPI or a specific repository. Consult the libopensonic documentation for detailed instructions.
  3. Patching libopensonic (Advanced):

    • Modify the Code: If updating doesn't solve the issue, you could consider patching libopensonic directly. This involves modifying the library's code to handle the missing is_dir field gracefully. For example, you could add a default value for is_dir if it's not present in the API response.
    • Caution: Patching code can be risky if not done carefully. Make sure to back up the original files before making any changes, and thoroughly test your modifications to avoid introducing new issues. It’s also a good idea to contribute your patch back to the libopensonic project so that others can benefit from your fix.
  4. MusicAssistant Configuration Tweaks:

    • Provider Settings: Explore the MusicAssistant configuration settings for the LMS provider. There might be options to adjust how MusicAssistant interacts with the LMS API, such as changing the API version or enabling/disabling specific features. Experimenting with these settings might help resolve the compatibility issues.
    • Metadata Refresh: Try refreshing the metadata within MusicAssistant. This forces MusicAssistant to re-fetch data from LMS, which might resolve inconsistencies or outdated information. This can be done through the MusicAssistant interface, usually under the library or settings section.
  5. LMS Server Configuration:

    • API Response Format: Investigate the LMS server configuration for options related to the API response format. Some servers allow you to customize the data returned by the API. If possible, configure LMS to include the is_dir field in its responses.
    • Plugin Conflicts: Check for any LMS plugins that might be interfering with the API. Sometimes, plugins can modify the API responses or introduce compatibility issues. Try disabling plugins one by one to see if any of them are causing the problem.
  6. Community Support and Forums:

    • Seek Advice: Don't hesitate to reach out to the MusicAssistant community forums or support channels. Other users might have encountered the same issues and found solutions. Sharing your error logs and configuration details can help others provide targeted advice.
    • Report Issues: If you suspect a bug in MusicAssistant or libopensonic, report it to the respective project maintainers. This helps them identify and fix issues in future releases. Be sure to include detailed information about your setup, error logs, and steps to reproduce the problem.

Digging Deeper: A Technical Perspective

For those of you who are a bit more technically inclined, let's delve deeper into why these errors are occurring. The errors we're seeing are primarily related to how data is serialized and deserialized between MusicAssistant and the LMS API.

Understanding Serialization and Deserialization

  • Serialization: This is the process of converting data structures (like Python objects) into a format that can be easily transmitted over a network or stored in a file (e.g., JSON).
  • Deserialization: This is the reverse process – converting serialized data back into usable data structures.

The mashumaro library, which is mentioned in the error logs, is a Python library that simplifies this process. It automatically handles the conversion between Python objects and JSON, but it relies on a consistent data structure. If the structure of the JSON data from the LMS API doesn't match the expected structure in MusicAssistant's code, mashumaro will throw an error.

The Role of libopensonic

libopensonic acts as a bridge between MusicAssistant and the Subsonic API (which LMS supports). It translates MusicAssistant's requests into Subsonic API calls and parses the responses. This means that any inconsistencies or missing fields in the Subsonic API responses will be surfaced by libopensonic.

Why the "is_dir" Field Matters

The is_dir field is crucial for MusicAssistant to determine whether an item in the music library is a directory (like an album or artist folder) or a file (like a song). This information is used for navigation, metadata handling, and playback control. If this field is missing, MusicAssistant can't correctly interpret the structure of the library, leading to errors.

Final Thoughts and Next Steps

Troubleshooting API issues can be a bit of a headache, but with a systematic approach, we can usually find a solution. The key is to carefully analyze the error logs, understand the underlying technologies, and try different solutions one at a time.

If you’re still facing issues, don’t hesitate to provide more error logs or details about your setup. The more information we have, the better we can help each other out.

I hope this article has been helpful, and let’s get our music playing smoothly again!