ARC download of ALAC track crashes RoonServer during sync (ref#EYBSI6)

Hi! What’s not quite right with Roon?

· None of the above quite fits

None of the above quite fits

· None of these quite match

Tell us what's going on

· # ARC/offline download of one decoder-rejected ALAC track repeatedly terminates the entire RoonServer process

**Severity:** High — all playback and connected clients are interrupted; the crash repeats when mobile sync retries.

## Summary

·
Reconnecting a mobile/ARC client so that an offline album download could continue caused RoonServer to terminate three times. Each termination occurred while Roon's mobile download service was transcoding the same local ALAC track at `LossyHigh` quality. The fatal exception is an unhandled `Roon.Audio.CorruptMediaException` in `Sooloos.Broker.Mobile.ETDPDownloadOpus.WorkerMethod()`.

The source file may genuinely be damaged or otherwise rejected by Roon's decoder. The bug is that failure of one background mobile download escapes its worker and terminates the entire RoonServer process. The service supervisor restarts RoonServer, but mobile sync later retries the item and can crash it again.

## Environment

·
- RoonServer 2.70 (build 1671), production, linuxx64
- RoonOS 2.1 (build 271), production
- Source: local ALAC, 16-bit/44.1 kHz, `.m4a`
- ARC/offline download quality: `LossyHigh`
- Offending item reported by Roon: `Portico Quartet / Isla / 07 - Life Mask.m4a`
- Normal audio playback was active during the first incident.

## Steps that triggered the fault

·
1. Configure a mobile/ARC client to download the album *Isla* for offline use.
2. Disconnect the client before the download completes.
3. Reconnect it so mobile sync resumes.
4. Roon logs `RespondDownload` and starts transcoding `07 - Life Mask.m4a`.
5. The Opus-download worker throws `Roon.Audio.CorruptMediaException` and the entire RoonServer process terminates.
6. RoonServer automatically restarts. When mobile sync retries the track, the process can terminate again.

## Expected result

·
Roon should mark the one track/download as failed, report the media error to the client, and keep RoonServer and unrelated playback running.

## Actual result

·
The exception is unhandled on the mobile-download worker thread and terminates RoonServer. All zones, clients, and extensions lose the Core until its supervisor restarts it.

## Repeated occurrences

·
| Crash (UTC) | Crash (EDT) | Next RoonServer start (UTC) | Result |
|---|---|---|---|
| 2026-08-03 21:37:40 | 17:37:40 | 21:37:42 | Same exception and mobile-worker stack |
| 2026-08-03 21:42:13 | 17:42:13 | 21:42:15 | Same exception and mobile-worker stack |
| 2026-08-03 22:11:40 | 18:11:40 | 22:11:42 | Same exception and mobile-worker stack |

This is process termination, not merely a client disconnect: each pre-crash log ends with the exception report, and the following log begins with `Starting RoonServer v2.70 (build 1671)` two seconds later.

## Crash signature

·
```text
Exception Source: Roon.Media
Exception Type: Roon.Audio.CorruptMediaException
Exception Target Site: MediaDecoderStream.ReadImp
Exception Message: Got CorruptFile while reading from stream

Roon.Audio.MediaDecoderStream.ReadImp(...)
Roon.Audio.AudioStream.Read(...)
Roon.Audio.PCMToFloatStream.ReadImp(...)
Roon.Audio.PolyphaseResamplerStream.ReadImp(...)
Roon.Audio.ConvertBitDepthStream.ReadImp(...)
Sooloos.Broker.Mobile.ETDPDownloadOpus.FeedEncoder(...)
Sooloos.Broker.Mobile.ETDPDownloadOpus.WorkerMethod()
System.Threading.Thread/StartHelper.Callback(...)
```

## Why this appears isolated to ARC/mobile sync

·
- Immediately before each exception, the log identifies the `[mobile] [Mobile] RespondDownload` path.
- The fatal stack terminates in `ETDPDownloadOpus.WorkerMethod`, not an active playback-zone encoder.
- The same album and track are retried after each automatic RoonServer restart.
- The first crash occurred during unrelated, healthy playback; the playback stream was not the file named by the fatal worker. ## Root cause of the source-file defect (established 2026-08-04)

The source file is genuinely malformed, and Roon’s decoder is correct to reject it. The defect is in the MP4
container structure, not the audio payload.

Walking the root-level atom chain of the offending file:

  @         0  ftyp  size=        32
  @        32  moov  size=     25296  end=25328
  @     25328  <non-ASCII>  size=3098241624   <-- extends 3,058,711,518 bytes past EOF

There is no mdat atom. Where the audio container header should begin, the bytes do not form a valid atom: the
type field is non-ASCII and the declared size (about 3.1 GB) exceeds the 39,555,434-byte file by roughly 3 GB.

Two known-good tracks from the same album and the same encoder show the expected structure:

05 - Life Mask Interlude:  ftyp(32) -> moov(43059) -> free(56954) -> mdat(4932283)
08 - Isla:                 ftyp(32) -> moov(55189) -> free(57113) -> mdat(32713295)

So free and the mdat header are absent in the offending file; the raw audio payload begins immediately after
moov with no container header.

The audio itself is intact. All 4,692 ALAC packets decode without error, yielding 435.75 s — exactly matching the
435,750ms Roon reports in [transcodestream]. Decoded-PCM MD5 is fb344b9153748d5e471e40b37f3c9e61.

Why other players do not fail. FFmpeg locates samples through the stco chunk-offset table in moov, which
holds absolute file offsets, so it never walks the root atom chain and never encounters the malformed header. It
decodes the file cleanly even with -err_detect +crccheck+bitstream+buffer. A decoder that validates container
structure — as Roon’s evidently does — reaches the bad atom and correctly raises CorruptFile. This explains why the
file appears healthy in most tools yet reliably terminates RoonServer.

Lossless repair. Remuxing with ffmpeg -i in.m4a -map 0:a -c:a copy -movflags +faststart out.m4a rebuilds a valid
ftyp -> moov -> free -> mdat chain and reproduces decoded-PCM MD5 fb344b9153748d5e471e40b37f3c9e61 — bit-identical
audio, valid container. Tags (title, artist, album, track) are preserved.

This narrows the report rather than weakening it. Roon is right to reject the file. The defect is solely that an
expected, recoverable media error on a background mobile-download worker escapes that worker and terminates the entire
RoonServer process. A malformed file anywhere in a library should not be able to crash the Core.

- Recent resource statistics showed ample memory and no out-of-memory exception. For example, immediately before the first crash Roon reported about 2.9 GB physical use, 542 handles, and 94 threads.

# Redacted evidence excerpts

·
Sensitive identifiers from the raw logs have been omitted: user ID, device serial, Core ID, public IP, client connection identifiers, and local host addresses. The library root and internal track IDs are also shortened below. The timestamps, media name, exception type, and decisive stack frames are unchanged.

## Crash 1 — 21:37:40 UTC / 17:37:40 EDT

·
text<br>08/03 21:37:35 [Local 08/03 17:37:35] Trace: [playback zone] [100% buf] [PLAYING @ 0:25/1:07] [unrelated active track]<br>08/03 21:37:39 [Local 08/03 17:37:39] Trace: [mobile] [Mobile] RespondDownload <track-id>, LossyHigh --> <library>/Portico Quartet/Isla/Portico Quartet - Isla - 05 - Life Mask Interlude.m4a<br>08/03 21:37:40 [Local 08/03 17:37:40] Trace: [mobile] [Mobile] RespondDownload <track-id>, LossyHigh --> <library>/Portico Quartet/Isla/Portico Quartet - Isla - 07 - Life Mask.m4a<br>08/03 21:37:40 [Local 08/03 17:37:40] Info: [transcodestream] transcoding <library>/Portico Quartet/Isla/Portico Quartet - Isla - 07 - Life Mask.m4a from StreamFormat(channels=2, bitspersample=16, samplerate=44100, isdts=False) to StreamFormat(channels=2, bitspersample=24, samplerate=48000, isdts=False) (435,750ms)<br>08/03 21:37:40 [Local 08/03 17:37:40] Info:<br> Exception Source: Roon.Media<br> Exception Type: Roon.Audio.CorruptMediaException<br> Exception Target Site: MediaDecoderStream.ReadImp<br> Exception Message: Got CorruptFile while reading from stream<br> ...<br> Sooloos.Broker.Mobile.ETDPDownloadOpus.FeedEncoder(...)<br> Sooloos.Broker.Mobile.ETDPDownloadOpus.WorkerMethod()<br><br>08/03 21:37:42 Info: Starting RoonServer v2.70 (build 1671) production on linuxx64<br>

## Crash 2 — 21:42:13 UTC / 17:42:13 EDT

·
text<br>08/03 21:42:08 [Local 08/03 17:42:08] Trace: [mobile] [Mobile] RespondDownload <track-id>, LossyHigh --> <library>/Portico Quartet/Isla/Portico Quartet - Isla - 05 - Life Mask Interlude.m4a<br>08/03 21:42:12 [Local 08/03 17:42:12] Trace: [mobile] [Mobile] RespondDownload <track-id>, LossyHigh --> <library>/Portico Quartet/Isla/Portico Quartet - Isla - 07 - Life Mask.m4a<br>08/03 21:42:12 [Local 08/03 17:42:12] Info: [transcodestream] transcoding <library>/Portico Quartet/Isla/Portico Quartet - Isla - 07 - Life Mask.m4a from StreamFormat(channels=2, bitspersample=16, samplerate=44100, isdts=False) to StreamFormat(channels=2, bitspersample=24, samplerate=48000, isdts=False) (435,750ms)<br>08/03 21:42:13 [Local 08/03 17:42:13] Info:<br> Exception Type: Roon.Audio.CorruptMediaException<br> Exception Message: Got CorruptFile while reading from stream<br> ...<br> Sooloos.Broker.Mobile.ETDPDownloadOpus.WorkerMethod()<br><br>08/03 21:42:15 Info: Starting RoonServer v2.70 (build 1671) production on linuxx64<br>

## Crash 3 — 22:11:40 UTC / 18:11:40 EDT

·
text<br>08/03 22:11:32 [Local 08/03 18:11:32] Info: [stats] 22098mb Virtual; 1342mb Physical; 513 Handles; 91 Threads<br>08/03 22:11:39 [Local 08/03 18:11:39] Trace: [library/mobilesync] Downloading <album-id> LibraryAlbum[<id>, Portico Quartet - Isla] ...<br>08/03 22:11:40 [Local 08/03 18:11:40] Trace: [mobile] [Mobile] RespondDownload <track-id>, LossyHigh --> <library>/Portico Quartet/Isla/Portico Quartet - Isla - 07 - Life Mask.m4a<br>08/03 22:11:40 [Local 08/03 18:11:40] Info: [transcodestream] transcoding <library>/Portico Quartet/Isla/Portico Quartet - Isla - 07 - Life Mask.m4a from StreamFormat(channels=2, bitspersample=16, samplerate=44100, isdts=False) to StreamFormat(channels=2, bitspersample=24, samplerate=48000, isdts=False) (435,750ms)<br>08/03 22:11:40 [Local 08/03 18:11:40] Info:<br> Exception Type: Roon.Audio.CorruptMediaException<br> Exception Message: Got CorruptFile while reading from stream<br> ...<br> Sooloos.Broker.Mobile.ETDPDownloadOpus.WorkerMethod()<br><br>08/03 22:11:42 Info: Starting RoonServer v2.70 (build 1671) production on linuxx64<br>

# Evidence provenance

·
The source logs were copied read-only from the RoonServer Data/RoonServer/Logs share immediately after the third incident. Raw logs are intentionally not included in this report because they contain private account, device, network, and library information.

| Raw Roon log | SHA-256 |
|—|—|
| RoonServer_log.03.txt | 931f4bdbe71d68a20e38d57b70d9cbb77aa45324024e44b682e94602d0ac8e9d |
| RoonServer_log.02.txt | 39e5f9801b7b2d3b5a2fb821ec94c191341e1f9bb4912fcfbfe14ddc0a5f3be6 |
| RoonServer_log.01.txt | f5d0d2684cd6895eb562814fd71415860cea287cb7de31e2ce6f36756a48d94e |
| RoonServer_log.txt after restart | d6ad860e098e8191a3f76f09d553586f3b03c01acd814148c79edb4225cf1805 |

Tell us about your home network

· Unifi Dream maxhine and Unifi switches

Hey @peter_richardson, welcome to the community.

This is a useful report, and the stack trace does point to the mobile download path rather than normal zone playback.

Because the file itself is being rejected as corrupt, the most likely next step is to confirm whether this happens with that specific track only or whether any other local file will trigger the same behavior during ARC download.

With that, can you please update all your Roon devices to the latest version and see if you still experience the issue?

Thank you :+1:

Thanks Benjamin. All my devices are current. (Just saw you issued an update a very short while ago :slightly_smiling_face:). Only the corrupt file seems to trigger this - it wont be an issue for me in the future but may stop downloads and cause frustration to anyone else seeing this on their system and not being able to modify the files. Don’t think I need to keep triggering it!

Hello @peter_richardson

It might be helpful to have the file(s) for testing on our end as well, can please upload them here and let us know?

https://workdrive.zohoexternal.com/collection/nqcgjac23027d90a441bda2c314de49d7958a/external

Yes, I had saved a copy.

The requested RoonServer logs have now been uploaded to your Media Uploader

roon-ref-EYBSI6-roonserver-logs-20260803.zip (1.2 MB)

These correspond to the CorruptMediaException crashes described in my report:

Happy to provide the offending media file or anything else you need. Hope this helps.

Thanks,

Peter

PS Since fixing this I am now able to enjoy many more downloaded albums to my phoe - could never work out why it always failed to smart-download much for me! Always thought it just wasn’t that smart :wink: