Summary
Two separate macOS desktop defects, both visible in setup.log as warmup failures:
[1788124440] [stemdeck] model warmup: WARMUP_FAILED sections 'utf-8' codec can't decode byte 0xa3 in position 45: invalid start byte
[1788124440] [stemdeck] model warmup: WARMUP_FAILED vocal_split [Errno 2] No such file or directory: 'ffmpeg'
The first one is not a warmup problem. It breaks automatic song sections entirely on macOS.
Reproduced on 0.16.0, macOS arm64, runtime pack StemDeck-runtime-macOS-arm64.tar.zst.
Bug 1: AppleDouble ._* files in the macOS runtime pack break allin1_infer
The installed runtime contains 30,239 AppleDouble sidecar files (._name, 163 bytes each, carrying a com.apple.provenance xattr). One of them lands inside matplotlib's style directory:
runtime/python/lib/python3.12/site-packages/matplotlib/mpl-data/stylelib/._seaborn-v0_8-bright.mplstyle
matplotlib globs *.mplstyle at import time and the AppleDouble name matches. Byte 45 of the AppleDouble header is 0xa3:
File "matplotlib/style/__init__.py", line 241, in <module>
_base_library = _read_style_directory(_BASE_LIBRARY_PATH)
File "matplotlib/style/__init__.py", line 209, in _read_style_directory
styles[path.stem] = rc_params_from_file(path, use_default_template=False)
File "matplotlib/__init__.py", line 902, in _rc_params_in_file
for line_no, line in enumerate(fd, 1):
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa3 in position 45: invalid start byte
matplotlib logs Cannot decode configuration file ... as utf-8. and re-raises, so import matplotlib.pyplot fails. That propagates:
allin1_infer/__init__.py -> .analyze -> .visualize -> import matplotlib.pyplot
Impact: every importer of allin1_infer fails, which includes app/pipeline/section_worker.py. Automatic song section detection is broken on macOS 0.16.0, not merely un-prewarmed. Deleting matplotlib's ._* files makes import allin1_infer succeed again, which confirms the cause.
Origin: scripts/macos/make-runtime-pack.sh copies the Python installation with ditto, which deliberately preserves extended attributes, then tars the staging tree without COPYFILE_DISABLE=1. macOS tar encodes those xattrs as ._ AppleDouble members. The Rust tar crate used by extract_tar_archive in desktop/src-tauri/src/main.rs has no AppleDouble awareness and writes them out as literal files.
Linux and Docker are unaffected: this is a macOS archive artifact.
Bug 2: warmup_models does not put the bundled FFmpeg on PATH
warmup_models in desktop/src-tauri/src/main.rs builds its Python command without the PATH block that start_backend has:
if let Some(ffmpeg_dir) = ffmpeg_dir_if_present(&data_dir) {
let existing = env::var_os("PATH").unwrap_or_default();
let mut paths = vec![ffmpeg_dir];
paths.extend(env::split_paths(&existing));
let joined = env::join_paths(paths).map_err(|e| e.to_string())?;
cmd.env("PATH", joined);
}
FFmpeg is present at <data>/ffmpeg/ffmpeg and recorded in config.json, but a Finder-launched .app inherits a minimal PATH (/usr/bin:/bin:/usr/sbin:/sbin), so audio_separator.separator.Separator shells out to ffmpeg and gets FileNotFoundError. Reproduced deterministically with env -i PATH=/usr/bin:/bin:/usr/sbin:/sbin.
Impact: smaller than bug 1. The real backend does get the right PATH, so the on-demand karaoke vocal split still works; it just pays the model download mid-job instead of during setup. Recurring on every launch in setup.log since timestamp 1787336901.
Proposed fix
scripts/macos/make-runtime-pack.sh: set COPYFILE_DISABLE=1 on both tar invocations and delete any ._* left in the staging tree before packing.
extract_tar_archive: skip archive entries whose file name starts with ._, so already-published runtime packs are handled too.
warmup_models: reuse the same ffmpeg_dir_if_present PATH block start_backend uses.
Summary
Two separate macOS desktop defects, both visible in
setup.logas warmup failures:The first one is not a warmup problem. It breaks automatic song sections entirely on macOS.
Reproduced on 0.16.0, macOS arm64, runtime pack
StemDeck-runtime-macOS-arm64.tar.zst.Bug 1: AppleDouble
._*files in the macOS runtime pack breakallin1_inferThe installed runtime contains 30,239 AppleDouble sidecar files (
._name, 163 bytes each, carrying acom.apple.provenancexattr). One of them lands inside matplotlib's style directory:matplotlib globs
*.mplstyleat import time and the AppleDouble name matches. Byte 45 of the AppleDouble header is0xa3:matplotlib logs
Cannot decode configuration file ... as utf-8.and re-raises, soimport matplotlib.pyplotfails. That propagates:allin1_infer/__init__.py->.analyze->.visualize->import matplotlib.pyplotImpact: every importer of
allin1_inferfails, which includesapp/pipeline/section_worker.py. Automatic song section detection is broken on macOS 0.16.0, not merely un-prewarmed. Deleting matplotlib's._*files makesimport allin1_infersucceed again, which confirms the cause.Origin:
scripts/macos/make-runtime-pack.shcopies the Python installation withditto, which deliberately preserves extended attributes, then tars the staging tree withoutCOPYFILE_DISABLE=1. macOStarencodes those xattrs as._AppleDouble members. The Rusttarcrate used byextract_tar_archiveindesktop/src-tauri/src/main.rshas no AppleDouble awareness and writes them out as literal files.Linux and Docker are unaffected: this is a macOS archive artifact.
Bug 2:
warmup_modelsdoes not put the bundled FFmpeg on PATHwarmup_modelsindesktop/src-tauri/src/main.rsbuilds its Python command without the PATH block thatstart_backendhas:FFmpeg is present at
<data>/ffmpeg/ffmpegand recorded inconfig.json, but a Finder-launched.appinherits a minimalPATH(/usr/bin:/bin:/usr/sbin:/sbin), soaudio_separator.separator.Separatorshells out toffmpegand getsFileNotFoundError. Reproduced deterministically withenv -i PATH=/usr/bin:/bin:/usr/sbin:/sbin.Impact: smaller than bug 1. The real backend does get the right PATH, so the on-demand karaoke vocal split still works; it just pays the model download mid-job instead of during setup. Recurring on every launch in
setup.logsince timestamp 1787336901.Proposed fix
scripts/macos/make-runtime-pack.sh: setCOPYFILE_DISABLE=1on bothtarinvocations and delete any._*left in the staging tree before packing.extract_tar_archive: skip archive entries whose file name starts with._, so already-published runtime packs are handled too.warmup_models: reuse the sameffmpeg_dir_if_presentPATH blockstart_backenduses.