Skip to content

Add 'Retries' column to Trackers tab#24388

Open
LWWZH wants to merge 7 commits into
qbittorrent:masterfrom
LWWZH:feat/add-failed-attempts-column
Open

Add 'Retries' column to Trackers tab#24388
LWWZH wants to merge 7 commits into
qbittorrent:masterfrom
LWWZH:feat/add-failed-attempts-column

Conversation

@LWWZH

@LWWZH LWWZH commented May 26, 2026

Copy link
Copy Markdown
Contributor

This PR adds a new "Retries" column to the Trackers tab (both desktop GUI and WebUI) that displays the number of consecutive failed announce attempts for each tracker endpoint.

Motivation

Users previously had no way to see how many times a tracker has failed to respond — they could only see the final status (Working/Not working/Tracker error/Unreachable). The raw failure count helps diagnose flaky trackers and understand retry behavior at a glance.

Implementation

libtorrent already exposes the consecutive failure count via lt::announce_infohash::fails. It was already read in TorrentImpl::updateTrackerEntryStatus() but only used as a boolean (fails > 0) to determine tracker state — the actual count was discarded.

The changes thread the value through all layers:

  • Backend data structs (TrackerEndpointStatus / TrackerEntryStatus): added int numFails = -1
  • Backend population (torrentimpl.cpp): stores ltAnnounceInfo.fails per-endpoint, then aggregates to tracker-level via std::max (consistent with how numPeers, numSeeds, etc. are aggregated)
  • GUI model (TrackerListModel): new COL_RETRIES column, display/sort support, right-aligned
  • Web API (torrentscontroller.cpp): serializes num_fails per endpoint and per tracker
  • WebUI (dynamicTable.js, prop-trackers.js): new fails column with data mapping

Behavior

  • Shows -1 as "N/A" (tracker not yet contacted)
  • Shows 0 when the tracker is working (no failures)
  • Shows the consecutive failure count when the tracker is in an error/unreachable/not-working state
  • The value resets to 0 by libtorrent after a successful announce

Closes #24013.

@glassez glassez changed the title feat: add 'Retries' column to Trackers tab showing consecutive announce failure count Add 'Retries' column to Trackers tab May 26, 2026
@glassez
glassez requested a review from a team May 26, 2026 09:37
@glassez glassez added WebUI WebUI-related issues/changes GUI GUI-related issues/changes Core Feature Implement new feature/subsystem WebAPI WebAPI-related issues/changes labels May 26, 2026
@glassez glassez added this to the 5.3 milestone May 26, 2026
@stalkerok

Copy link
Copy Markdown
Member
  • right-aligned

The values are left-aligned.

In the minimized state, the tracker continues to accumulate errors. You need to bring the best value to the forefront.

2026-05-26_132522

@thalieht

Copy link
Copy Markdown
Contributor

GUI:

  • The "retries" column in the header's context menu is last but in the order of columns it is initially 3rd unlike all the other columns

WebUI:

  • The "retries" column in the header's context menu is 4th from last while in GUI it's the last.
  • When sorting by this column, DHT, PeX and LSD items are not excluded (should always be at the top).
    "Next announce" and "Min announce" columns have the same problem.

@LWWZH

LWWZH commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

@stalkerok

  • Right-alignment: Added COL_RETRIES to Qt::TextAlignmentRole in data() — it was present in headerData() but missing from the cell data alignment switch.
  • Minimized tracker aggregation: Changed std::maxstd::min for numFails at tracker level, so the best (lowest) failure count is shown rather than the worst.

@thalieht

  • GUI column order: Moved COL_RETRIES from enum position 11 (after COL_MIN_ANNOUNCE) to position 8 (after COL_TIMES_DOWNLOADED, before COL_MSG), matching the WebUI order and grouping it with other numeric stat columns.
  • WebUI sorting: Added compareRows = sortMixed for fails and compareRows = sortNumbers for nextAnnounce/minAnnounce, so DHT/PeX/LSD rows (_sortable: false) stay at top when sorting by these columns.

I've resolved all review comments, changes are in 4 files total: torrentimpl.cpp, trackerlistmodel.h, trackerlistmodel.cpp, dynamicTable.js.

@stalkerok

Copy link
Copy Markdown
Member

Only I don't have a button to run the workflow?

@glassez

glassez commented May 26, 2026

Copy link
Copy Markdown
Member
  • Minimized tracker aggregation: Changed std::maxstd::min for numFails at tracker level, so the best (lowest) failure count is shown rather than the worst.

Shouldn't it be 0 for Working trackers? I thought that's what @stalkerok meant.

@xavier2k6

Copy link
Copy Markdown
Member

Only I don't have a button to run the workflow?

GitHub seem to be having issues as you're not the only one who isn't seeing a workflow button.....there's issues with badges/tokens too.

@stalkerok stalkerok closed this May 26, 2026
@stalkerok stalkerok reopened this May 26, 2026
@thalieht

Copy link
Copy Markdown
Contributor

This happens the first time when running qBt with this PR with an existing Qt6\TorrentProperties\TrackerListState key in the config file. If i change some things in the header i.e. resize a column, hide a column or restart qBt, the problem goes away. I noticed it at the beginning of the PR and it remains.
Here's my default key if anyone wants to test:

Click

[GUI] Qt6\TorrentProperties\TrackerListState=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4L\0\0\0\v\x1\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\v\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1)

Screencast_20260526_174146.webm
  • After the last push everything in this column stays "N/A".

@stalkerok

Copy link
Copy Markdown
Member

Works as expected.
To ensure proper operation after the upgrade (with an existing “TrackerListState” entry), the client must be restarted.

stalkerok
stalkerok previously approved these changes May 29, 2026
@stalkerok

Copy link
Copy Markdown
Member

The retry counter is stopped at 127.

@LWWZH

LWWZH commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

The retry counter is stopped at 127.

@stalkerok
This is a libtorrent limitation. The fails field in announce_infohash is defined as a 7-bit bitfield (std::uint8_t fails : 7), so its maximum value is 127. qBittorrent passes this value through directly and has no control over the upper bound — the cap is enforced at the library level.

@stalkerok

Copy link
Copy Markdown
Member

It looked like that. I guess there's nothing that can be done about it in qBit?

@thalieht

Copy link
Copy Markdown
Contributor

The fails field in announce_infohash is defined as a 7-bit bitfield (std::uint8_t fails : 7), so its maximum value is 127.

I thought the max is 255 but in qBt it is cast into a signed variable making half of them negative.
Anyway 127 or 255 IMO it doesn't matter.

Comment thread src/base/bittorrent/torrentimpl.cpp Outdated
Comment thread src/webui/api/torrentscontroller.cpp
Co-authored-by: Vladimir Golovnev <glassez@yandex.ru>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Retries” column to the Trackers tab (desktop GUI + WebUI) by surfacing libtorrent’s consecutive announce failure count (fails) through backend status structs, the Web API, and both UIs.

Changes:

  • Extend tracker status data (TrackerEndpointStatus / TrackerEntryStatus) with numFails and populate it from libtorrent.
  • Expose num_fails via api/v2/torrents/trackers and render/sort it in the WebUI trackers table.
  • Add a “Retries” column to the desktop GUI tracker list model with display + sort support.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
WebAPI_Changelog.md Documents the addition of num_fails to the trackers API response.
src/webui/www/private/scripts/prop-trackers.js Maps num_fails from API response into table row data for trackers/endpoints.
src/webui/www/private/scripts/dynamicTable.js Adds the “Retries” column definition and sorting behavior for the WebUI trackers table.
src/webui/api/torrentscontroller.cpp Serializes num_fails for both tracker entries and endpoint entries in torrents/trackers.
src/gui/trackerlist/trackerlistmodel.h Introduces a new GUI model column (COL_RETRIES).
src/gui/trackerlist/trackerlistmodel.cpp Plumbs numFails into GUI tracker model items, header, alignment, display, and sort roles.
src/base/bittorrent/trackerentrystatus.h Adds numFails fields to tracker entry/endpoint status structs.
src/base/bittorrent/trackerentrystatus.cpp Resets numFails in TrackerEntryStatus::clear().
src/base/bittorrent/torrentimpl.cpp Populates endpoint numFails from libtorrent and aggregates it to the tracker entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

trackerEndpointStatus.numSeeds = ltAnnounceInfo.scrape_complete;
trackerEndpointStatus.numLeeches = ltAnnounceInfo.scrape_incomplete;
trackerEndpointStatus.numDownloaded = ltAnnounceInfo.scrape_downloaded;
trackerEndpointStatus.numFails = ltAnnounceInfo.fails;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

numFails is always set from ltAnnounceInfo.fails, which is typically 0 before the tracker has ever been contacted. This makes the new Retries column show 0 instead of the intended “N/A” for never-contacted trackers/endpoints (as described in the PR). Consider translating the “not contacted yet” case to -1 at the source.

Does it look bad if Retries column shows 0 for never-contacted trackers/endpoints? IMO, there is nothing contradictory about this.

Comment on lines +264 to +269
if (endpointStatus.numFails >= 0)
{
trackerEntryStatus.numFails = (trackerEntryStatus.numFails < 0)
? endpointStatus.numFails
: std::min(trackerEntryStatus.numFails, endpointStatus.numFails);
}
Comment on lines 64 to 66
COL_TIMES_DOWNLOADED,
COL_RETRIES,
COL_MSG,
Comment thread WebAPI_Changelog.md
Comment on lines +5 to +6
* [#24388](https://github.com/qbittorrent/qBittorrent/pull/24388)
* `torrents/trackers` endpoint now includes `num_fails` field for tracker entries, reporting the number of consecutive failed announce attempts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Core Feature Implement new feature/subsystem GUI GUI-related issues/changes WebAPI WebAPI-related issues/changes WebUI WebUI-related issues/changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add the "Retries" column on the Trackers tab

6 participants