This release includes breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
ReleasePort's take
Moderate signalThe release adds client‑side upload validation that blocks files over 100 MB or with unsupported formats before any server round‑trip, and it enhances desktop setup errors with actionable messages and a Retry button.
Why it matters: Frontend now rejects oversized or disallowed uploads (max 100 MB) pre‑emptively, reducing unnecessary network traffic and potential backend strain; desktop users receive clearer error guidance, improving usability. Measurable trigger: file size limit of 100 MB.
Summary
AI summaryBackend download retries, configurable pipeline timeouts, registry schema migration, frontend client‑side upload validation, and desktop setup actionable error messages.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Security | Medium |
Windows portable packages scanned with ClamAV in CI before upload. Windows portable packages scanned with ClamAV in CI before upload. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Download retries on transient network errors now retry up to 3 times with exponential backoff. Download retries on transient network errors now retry up to 3 times with exponential backoff. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Job registry runs _migrate() function on load to upgrade persisted schemas incrementally. Job registry runs _migrate() function on load to upgrade persisted schemas incrementally. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Client-side upload validation rejects files over 100 MB or with unsupported formats before server round-trip. Client-side upload validation rejects files over 100 MB or with unsupported formats before server round-trip. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Feature | Medium |
STEM_NAMES fetched from GET /api/config on startup, reflecting backend changes without frontend update. STEM_NAMES fetched from GET /api/config on startup, reflecting backend changes without frontend update. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Unsupported file type errors now use showError() toast instead of alert(). Unsupported file type errors now use showError() toast instead of alert(). Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Desktop setup flow includes actionable error messages with recovery hints and Retry button. Desktop setup flow includes actionable error messages with recovery hints and Retry button. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Dependency | Medium |
macOS arm64 and x64 DMGs and runtime packs built on macOS Woodpecker agent before upload. macOS arm64 and x64 DMGs and runtime packs built on macOS Woodpecker agent before upload. Source: llm_adapter@2026-05-21 Confidence: low |
— |
| Bugfix | Medium |
localStorage error visibility now emits console.warn instead of being silently swallowed. localStorage error visibility now emits console.warn instead of being silently swallowed. Source: llm_adapter@2026-05-21 Confidence: low |
— |
| Refactor | Medium |
Hardcoded timeouts are now named constants in config.py, overridable via environment variables. Hardcoded timeouts are now named constants in config.py, overridable via environment variables. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Refactor | Medium |
Every pipeline log line now prefixed with [job_id] for job tracing. Every pipeline log line now prefixed with [job_id] for job tracing. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Refactor | Medium |
SSE-driven state updates deferred by one tick to prevent clobbering in-progress user interactions. SSE-driven state updates deferred by one tick to prevent clobbering in-progress user interactions. Source: llm_adapter@2026-05-21 Confidence: high |
— |
| Refactor | Medium |
Removed leftover console.log call in player.js. Removed leftover console.log call in player.js. Source: llm_adapter@2026-05-21 Confidence: low |
— |
Full changelog
## v0.4.0-alpha.3
[!IMPORTANT]
macOS users run this after installing:xattr -dr com.apple.quarantine /Applications/StemDeck.appmacOS Gatekeeper will block the app on launch without this step. Proper code signing is planned for a future release.
What's new in alpha.3
This release applies the papaya improvement cycle ÔÇö 11 fixes across the backend pipeline, frontend, and desktop setup flow.
Backend
Download retries on transient network errors
yt-dlp downloads now retry up to 3 with exponential backoff (2 / 4 / 8 s) on transient failures ÔÇö SSL errors, connection resets, DNS blips, timeouts. Non-retriable errors (404, private video, geo-block, age-restricted) still fail immediately with no retry.
Pipeline timeout constants
Hardcoded timeouts scattered across pipeline files (300 s for FFmpeg, 120 s for analysis, 1800 s for Demucs stall detection) are now named constants in config.py, overridable via environment variables (STEMDECK_TIMEOUT_FFMPEG, STEMDECK_TIMEOUT_ANALYZE, STEMDECK_TIMEOUT_DEMUCS_STALL).
Registry schema migration
The job registry now runs a _migrate() function on load that upgrades persisted schemas incrementally. The existing "version" field is now acted on ÔÇö adding or changing schema fields in future releases will not break already-completed jobs on restart.
Job correlation in logs
Every pipeline log line is now prefixed with [job_id], making it straightforward to trace a single job across the download  analyze  separate stages in log output.
Frontend
Client-side upload validation
File size and type are now validated in the browser before the upload begins. Files over 100 MB or with unsupported formats are rejected immediately with a toast ÔÇö no round-trip to the server needed.
Stem names from API
STEM_NAMES is no longer hardcoded in JavaScript. The frontend fetches the authoritative list from GET /api/config on startup, so adding or renaming a stem in the backend is reflected in the UI without a separate frontend change.
SSE race condition guard
SSE-driven state updates are now deferred by one tick (setTimeout(..., 0)) so in-progress user interactions (mixer moves, stem toggles) are not clobbered by a concurrent server-sent event.
localStorage error visibility
localStorage reads and writes that fail (e.g. quota exceeded) now emit a console.warn instead of being silently swallowed, making persistence failures visible during debugging.
Removed debug console.log
A leftover console.log call in player.js has been removed.
Replaced alert() with toast
Unsupported file type errors that previously used alert() now use the in-app showError() toast ÔÇö accessible, mobile-friendly, and consistent with the rest of the UI.
Desktop setup
Actionable error messages
Each terminal error state in the setup flow now includes a specific recovery hint and a working Retry button ÔÇö e.g. "Check that your disk has at least 2 GB free and click Retry" instead of a bare error string.
Artifact build
- macOS arm64 and x64 DMGs and runtime packs were built and inspected on a macOS Woodpecker agent before upload.
Artifact scan
- Windows portable packages were scanned with ClamAV in CI before upload.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About stemdeckapp/stemdeck
All releases →Related context
Related tools
Earlier breaking changes
- v0.6.0-alpha.1 Moves library and stems storage from `~/Library/Application Support/` to `~/Documents/StemDeck/`.
Beta — feedback welcome: [email protected]