#3083·webtorrent

file.deselect() drops shared pieces from the active download pool, causing torrents to hang at 99%

Author: kaisercCreated Jul 7, 2026Updated Jul 10, 2026
Labelsbugaccepted

Bug Report: file.deselect() drops shared pieces from the active download pool, causing torrents to hang at 99%

Description

When a piece is shared across the boundary of two files, calling file.deselect() on one of the files causes webtorrent to completely remove that shared piece from this._selections (via this._torrent.deselect()).

If the adjacent file sharing that piece is still selected, it will never finish downloading because its final piece has been stripped from the active selection pool. This causes the torrent to hang indefinitely at 99.9% and never emit the 'done' event.

Steps to Reproduce

  1. Start downloading a torrent that contains at least two adjacent files (e.g., a large .mp4 followed immediately by a small .srt file). By default, webtorrent selects both files.
  2. Call file.deselect() on the small .srt file.
  3. webtorrent calls torrent.deselect(startPiece, endPiece). Because the .srt file shares its startPiece with the .mp4 file's endPiece, that piece is dropped from this._selections.
  4. Observe the download progress. The .mp4 file will download all of its pieces except the final one, getting permanently stuck at 99.9% completion.

Expected Behavior

file.deselect() should be aware of cross-file piece boundaries. It should ideally check if a piece is still required by another currently-selected file before unconditionally stripping it from the selection pool.

Alternatively, file.deselect() could simply lower the priority of the piece rather than removing it entirely if it's shared.

Workaround

For anyone experiencing this, you can manually patch the piece array by immediately re-calling file.select() on the files you do want after calling deselect() on the ones you don't:

javascript
// Deselect the unwanted files
for (const f of unwantedFiles) {
  f.deselect();
}

// Immediately re-select the wanted files.
// This forces webtorrent to restore any shared pieces that were just dropped!
for (const f of wantedFiles) {
  f.select();
}

Environment

  • WebTorrent version: v2.x / v3.x
  • Node.js version: (Any)