#24916·qBittorrent

Full recheck intermittently leaves one internal piece missing after same-hash removal/re-add; later SHA1 and recheck pass

Author: seeARMSCreated Sep 14, 2026Updated Sep 14, 2026

qBittorrent & operating system versions

  • qBittorrent-nox: 5.2.3, 64-bit (current stable release when checked on 2026-09-14).
  • OS: Debian GNU/Linux 13 (trixie), x86_64 LXC; host kernel Linux 6.8.12-15-pve.
  • Qt: 6.11.2; libtorrent-rasterbar: 2.0.14.0; Boost: 1.92.0; OpenSSL: 4.0.2; zlib: 1.3.2, reported by /app/buildInfo.
  • Storage: NFSv3 media mount shared into the application containers. Existing media is hardlinked into a separate final torrent tree.
  • Installation: executable outside the distribution's qbittorrent-nox package; exact build provenance has not yet been verified.
  • Orchestrator: a locally modified qui v1.29.0 using the qBittorrent Web API. Its isolated small-file recovery workflow is custom, not a claim about stock qui behavior. No qBittorrent upgrade or local-disk comparison was performed for this investigation.

What is the problem?

Three newly added final torrents were left with exactly one internal 16 MiB media piece recorded as missing after full checks. Later independent reads of each reported range matched the SHA1 in the target's v1 metainfo; a subsequent full recheck completed without downloading any final-torrent payload.

These were fresh direct /api/v2/torrents/info, /torrents/files and /torrents/pieceStates observations, not just cached progress in qui. The final torrents were stoppedDL, amount_left=16777216, with all files selected at priority 1 and downloaded=downloaded_session=0.

Anonymized case labels below represent three real observations, not synthetic reproduction results. Piece indices are zero-based.

Case Missing piece / total pieces Independent later check Eventual result
TV-A 591 / 698 Target piece SHA1, adjacent target pieces and corresponding original-source pieces matched their metainfo. Later full recheck: 698/698; final download counters remained zero.
TV-B 267 / 490 Target piece SHA1, adjacent target pieces and two covering 8 MiB pieces of an existing same-inode counterpart matched. That counterpart was not the original directory source. Later full recheck: 490/490; final download counters remained zero.
Movie-C 771 / 2,799 Target piece SHA1 and two covering 8 MiB pieces of an existing same-inode counterpart matched. The precise original source torrent was not established from retained logs. An initial check and one retry were incomplete. A separately reviewed later full recheck passed 2,799/2,799; final download counters remained zero.

The failed ranges were wholly inside the media files, away from the recovered sidecar boundaries. The sidecars themselves were complete. File identity, size and modification time remained stable over the independent observation intervals. This establishes a discrepancy between recorded verification and bytes read later, not what bytes the failing hash operation saw.

Expected: when the complete on-disk bytes match the metainfo, a full recheck should consistently record them as complete. I cannot yet establish whether a failing check read different bytes transiently or whether the discrepancy arose elsewhere.

Steps to reproduce

There is no deterministic reproduction yet. The observed preceding workflow was:

  1. A custom qui recovery path adds a v1 torrent stopped into an isolated temporary destination. Existing media is never placed in that writable staging destination. All file priorities are cleared, then only permitted small extras are selected. The complete affected-piece budget is at most 50 MiB.
  2. Resume that isolated torrent to obtain the extras. Stop it, confirm it is stopped, remove it, and confirm fresh direct API absence. Independently verify the affected piece hashes using original media plus staged extras, then copy the verified extras into the owned final tree beside existing hardlinked media and clean the staging tree.
  3. Re-add the same infohash at the different final destination, with autoTMM=false, stopped, and skip_checking=false. Freshly validate the final path and ordered file layout and explicitly set every file priority to 1. Request a full recheck before any final payload download is allowed.
  4. In the three cases above, the final check ended one internal piece short. Keep the target stopped, export its existing metainfo locally, and independently hash exactly the reported bad range and the covering pieces from separate counterpart metainfo.
  5. A later stopped full recheck passed. Resume only after fresh aggregate, piece and individual-file completion was confirmed.

Most additions in the same workflow passed. The sample does not establish an incidence rate or a regression against another qBittorrent/libtorrent version. No failing-time read trace, actual libtorrent digest, file-descriptor identity or disk-cache state was captured. NFS visibility/I/O, client bookkeeping and the custom removal/re-add ordering remain hypotheses; this report does not attribute the cause to qBittorrent, libtorrent or NFS.

Additional context

  • #24845 concerns lost /sync/maindata delta fields while direct /torrents/info is correct. Here direct info and piece states both reported incomplete data, so that fix alone does not explain the observations.
  • #21388 describes lost boundary data in a .parts file after removal. Here every final file was present and selected, and the independently checked missing piece was internal to the media file.
  • Closed #11971 has a related symptom on much older versions; I have not established a common cause.

Which diagnostic capture would best distinguish a transient disk read from verification-state/lifecycle behavior on the next occurrence? In particular, is direct API absence sufficient before re-adding the same hash at another destination, or is there an additional completion signal that a Web API orchestrator should wait for? I can work toward a small synthetic, non-private reproduction; none is supplied or claimed here.

Log(s) & preferences file(s)

Relevant qBittorrent log excerpt for TV-A on 2026-09-14, UTC; only the torrent name has been replaced. The first add is the isolated stage and the second is the final destination. The resumed entries are preserved as logged, not used as proof of a final payload download; the final download counters stayed zero.

06:53:05 Added new torrent. Torrent: "TV-A"
06:53:06 Torrent resumed. Torrent: "TV-A"
06:53:06 Torrent download finished. Torrent: "TV-A"
06:53:18 Torrent stopped. Torrent: "TV-A"
06:53:19 Torrent removed. Torrent: "TV-A"
06:53:19 Added new torrent. Torrent: "TV-A"
06:53:19 Torrent resumed. Torrent: "TV-A"
06:54:09 Torrent stopped. Torrent: "TV-A"

No explanatory hash/file/I/O warning was found for TV-A in the retained 06:50–06:55 client log window; the corresponding guest and host kernel journal windows had no entries. This limited observation does not rule out a transient read problem. Movie-C's stopped observation still showed the missing piece at 12:37 UTC; its later recheck began at 12:40:22 and passed by 12:42:36, with both final download counters still zero at 12:45:17.

Relevant /app/preferences values collected read-only after the incidents (numeric enum values preserved):

json
{
  "disk_io_type": 3,
  "disk_io_read_mode": 1,
  "disk_io_write_mode": 1,
  "recheck_completed_torrents": false,
  "incomplete_files_ext": false,
  "preallocate_all": false,
  "use_unwanted_folder": false,
  "temp_path_enabled": false,
  "torrent_content_layout": "Original",
  "max_active_checking_torrents": 1,
  "file_pool_size": 100,
  "disk_cache": 1024,
  "disk_cache_ttl": 600,
  "async_io_threads": 10,
  "checking_memory_use": 32,
  "enable_coalesce_read_write": false,
  "save_resume_data_interval": 60
}

This is a scoped settings transcription, not a complete preferences attachment. Private metainfo, filenames, tracker URLs, credentials and full operational logs are omitted. The current evidence cannot independently exclude other processes or hardware, or prove that every earlier read returned the bytes later observed.