MuseScore Studio 4 on Void Linux (and other non-systemd distributions) fails to initialize its audio sampling engine, MuseSampler, with the following error:
MuseSamplerLibHandler::init | Could not init lib
MuseSamplerResolver::init | Could not init MuseSampler: /home/<username>/.local/share/MuseSampler/lib/libMuseSamplerCoreLib.so, version: 0.105.1
MuseScore launches and the UI works fine, but all MuseSounds instruments are
unavailable. The same AppImage with the same MuseSounds installation works
perfectly on Fedora Linux. This post documents the full investigation, including
reverse engineering the closed-source libMuseSamplerCoreLib.so, and the fix.
Testing Environment
- Void Linux (glibc), runit init
- Artix Linux, OpenRC init
- Fedora Linux, systemd init
Initial Debugging
Ruling Out Missing Dependencies
The first suspicion was missing
shared libraries. Running ldd on the sampler library showed all dependencies
resolving cleanly with no not found entries. The system was running glibc, not
musl, so libc compatibility was not the issue.
Tracing Runtime Behavior
Since ldd was clean, the failure had to be
happening during runtime initialization. Extracting the AppImage into a squashfs and running
strace on the binary revealed the library was opening successfully (returning a
valid file descriptor), but something during init was causing it to fail.
symbol lookup error: /home/<username>/.local/share/MuseSampler/lib/libMuseSamplerCoreLib.so:
undefined symbol: _ZN3DRM9AntiDebug24scheduleThreadTimedCrashEv
Demangled, this is DRM::AntiDebug::scheduleThreadTimedCrash() - a DRM callback
that the sampler library expects the host binary to export. However, this error
appeared on both the non-systemd operating systems and the working Fedora system, making
it a red herring. The dynamic library handles this missing symbol gracefully.
Reverse Engineering with Ghidra
Process Name Whitelist
Reverse engineering libMuseSamplerCoreLib.so in Ghidra revealed the ms_init
function. Near the top of the function is an early-exit check:
cVar2 = FUN_00406510();
if (cVar2 == '\0') {
return 0xffffffff;
}
Decompiling FUN_00406510 revealed a process name whitelist. The function reads
the executable path (via /proc/self/exe or argv[0]), extracts the basename after
the last /, and checks it against three strings:
- “MuseScore-4”
- “MuseScore-5”
- “mscore”
The AppImage binary is named mscore4portable, which matches the last string.
This seems to be a check to ensure the dynamic library is only initialized from
within a legitimate MuseScore binary.
Instrument Folder Validation
Continuing deeper into ms_init, the next significant check was FUN_00405790.
This function calls getenv("MUSESAMPLER_INSTRUMENT_FOLDER") and, if set,
validates the path. If not set, it calls FUN_00405e40, which opens
and parses the config file at ~/.local/share/MuseSampler/.config to find the
instrument folder path. In this case, the config file contained:
/home/<username>/Muse Sounds
Both code paths ultimately call FUN_00328cc0 to validate the instrument folder.
Inside that function, it verifies the existence of a .instruments file inside
the sounds folder, then calls FUN_00416390 which performs a machine fingerprint
comparison.
Reverse Engineering the Fingerprint Check
FUN_00416390 is the core validator. Its logic:
- Verifies
<instrument_folder>/.instrumentsexists - Calls
FUN_0040d800to compute a machine-specific fingerprint - Base64-encodes that fingerprint:
*(char *)((long)puVar8 + sVar14) =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
[iVar5 >> ((char)uVar12 - 6U & 0x1f) & 0x3f];
- Reads a stored fingerprint from
.instrumentsvia a separate lookup function - Compares the two with
bcmp- if they don’t match, init fails
Decompiling FUN_0040d800 revealed exactly how the fingerprint is generated:

std::ifstream::ifstream((ifstream *)local_228,"/etc/machine-id",8);
// ...
if (iVar5 == 0) {
iVar5 = FUN_001d8160(local_260,"MuseHubIsAwesome",0x11); // Sets HMAC key
if (iVar5 != 0) goto LAB_0040d916;
iVar5 = FUN_001d83e0(local_260,local_280,local_278); // Processes machine-id
if (iVar5 != 0) goto LAB_0040d916;
iVar5 = FUN_001d8400(local_260,&local_248); // Produces 32-bype output
if (iVar5 != 0) goto LAB_0040d916;
}
The function reads /etc/machine-id, runs it through a keyed hash function using
the hardcoded key "MuseHubIsAwesome", and produces a 32-byte fingerprint. This
fingerprint is base64-encoded and stored in .instruments when MuseSounds Manager
downloads an instrument pack. On subsequent launches, MuseSampler recomputes the
fingerprint and compares it against the stored value.
The Root Cause
There are two distinct but related problems:
Problem 1: Void Linux is missing /etc/machine-id. Void does not create
/etc/machine-id by default. Its machine ID lives at
/var/lib/dbus/machine-id. Since FUN_0040d800 exclusively reads
/etc/machine-id, the fingerprint computation fails entirely on Void - the file
simply isn’t there to read. This means MuseSounds Manager generates a bad or
empty fingerprint when writing .instruments, and MuseSampler can never verify
it successfully on subsequent launches.
Problem 2: .instruments contains a bad fingerprint and needs to be
regenerated. Even on Artix Linux, which does have /etc/machine-id, MuseSampler
still failed on a fresh install. The fix in both cases was the same: delete
.instruments and re-download an instrument pack, forcing MuseSounds Manager to
regenerate it with a valid fingerprint. The exact reason MuseSounds Manager
generates a bad .instruments on non-systemd distros on the first run is not
fully clear, but may relate to the absence of a proper logind session when
MuseSounds Manager first runs.
The Fix
In order to fix this, it’s as simple as deleting the existing .instruments
file, and re-download any instrument pack via MuseSounds Manager.
rm ~/Muse\ Sounds/.instruments
Non-systemd distributions and others with /etc/machine-id missing will need to
create a symlink to the dbus machine ID:
sudo ln -s /var/lib/dbus/machine-id /etc/machine-id
Affected Distributions
Any Linux distribution that does not create /etc/machine-id by default will hit
this issue. This includes Void Linux and potentially other non-systemd distributions.
Why Fedora Works Out of the Box
Fedora uses systemd, which writes /etc/machine-id during first boot via
systemd-machine-id-setup.
MuseSounds Manager can read it successfully, generates a valid fingerprint, and
stores it in .instruments. MuseSampler verifies it correctly on every
subsequent launch. On non-systemd distros, something about the environment
during the initial MuseSounds Manager run causes it to write a bad fingerprint
into .instruments. On Void the cause is clear - /etc/machine-id simply
doesn’t exist. On Artix the cause is less obvious but the symptom and fix are
the same.
See Also
MuseScore GitHub Issue #32911 - MuseSampler fails to initialize on non-systemd Linux distributions