Trackers and Announces - Kheopsian/Hydranos GitHub Wiki

πŸ‡¬πŸ‡§ English Β· πŸ‡«πŸ‡· FranΓ§ais

Trackers and Announces

Applies to Hydranos 4.4.

For anyone who seeds on trackers with Hydranos, above all private ones: the Trackers tab, editing one torrent's tracker list, and what Hydranos sends to a tracker and when: which settings apply per host, which event is sent at each step, and what it adds around the announces (a scrape for torrents not announced yet, stopped on remove and on a clean shutdown).

How the race and hoard engines differ in general: Engines: Race and Hoard. Seed obligations and the drain: Race Drain, Graduation and Seed Obligations. Terms: Concepts and Glossary.

The Trackers tab

The Trackers tab has one row per tracker host (for example tracker.example.org), not one row per URL. A row appears when:

  • a torrent in the catalogue names that host, whether or not it has been announced to yet (so you can set a passkey before the first announce);
  • or an announce to it succeeded or failed;
  • or you saved a passkey or an announce IP family for it.

The rows cover every engine of this instance added together. The catalogue count uses the host as written in the URL, but errors, self-checks, the breaker and the passkey/family matching use the lowercased host: a failing Tracker.Example.org shows its errors on a separate tracker.example.org row.

Columns

Column What it shows
Tracker the host
Torrents how many torrents in the catalogue name this host (a torrent with the host in two tiers counts once)
Status ok (an announce answered), not announced (named by a torrent, never announced yet), error. A self-check verdict tag can follow it (see below). When the tracker has a problem, a severity replaces the whole cell, verdict included: needs action (red), unreachable (amber) or acknowledged (muted)
Passkey set if a passkey override exists, - otherwise
Min seed the seed obligation: 48h, 0h, or - (undeclared)
Announce the IP family: auto, v4 or v6
Errors (1h) announce failures of the last 60 minutes by class, e.g. timeout x12, rate_limited x3; click it to open the error details
Actions Mute / Unmute, Hide / Unhide, Edit

Severity rules:

  • needs action (red): the tracker rejected the passkey (invalid_passkey), or the self-check found this instance missing from one address family's peer list (v4_missing, v6_missing) or from both (absent).
  • unreachable (amber): rate_limited, timeout, dns or connect errors.
  • Torrents the tracker no longer knows (unknown_torrent) are not counted as a fault: there is nothing to fix on the tracker side.

The tab carries a red or amber badge with the number of red or amber trackers, counted in distinct trackers across all engines (a tracker red on both race and hoard counts once; red wins over amber). Every engine feeds the error counts, the severities and the badge, extra engines included (see Monitoring and Logs).

Self-check: a seed normally asks a tracker for no peers. One seed announce in 64 (one process-wide counter) asks for 50 peers and records whether this instance's address is in the list. Until a host has a verdict, every seed announce to it asks for 50, as does a seed found absent from both families. The verdict (ok, unknown, v4_missing, v6_missing, absent) is a tag in the Status cell; its age and swarm size are in the tag's tooltip. unknown is not an error and is shown grey: a tracker may leave the asking peer out of its own reply, so an absence alone proves nothing; v4_missing / v6_missing (one family seen, not the other) is what points to a problem.

Error details and error classes

Clicking a count in Errors (1h) opens Errors in the last hour: <host>: per engine and class, the tracker's own messages (URLs and passkeys redacted), count, age, event and torrent. For the hoard engine, Show the torrents opens the Hoard tab filtered on that tracker and error.

Two different sets of class names exist:

Where Classes
Trackers tab, Errors (1h) (announce side) rate_limited, timeout, invalid_passkey, unknown_torrent, dns, connect, http_error, udp_proxied, other. When both address families failed, only the IPv4 message is classified. udp_proxied is Hydranos' own refusal, not a tracker fault: a udp:// tracker of an engine whose announces go through a proxy (see UDP trackers); the Errors (1h) cell shows it as that refusal's full sentence, the class name appears in the error details (and in the row tooltip only when the tracker is also marked needs action, unreachable or acknowledged).
Race and Hoard lists, error filter (torrent side) Dead on the tracker, Bad passkey, Rate-limited, Tracker unreachable, Other error

The torrent-side class is each torrent's last error, cleared by the next successful announce: a current state, not a history.

Setting a passkey, minimum seed and IP family

Click Edit on a row, or + Manual host for a host that has no row yet. The form has:

Field Meaning
Host the tracker host as shown in the Tracker column, e.g. tracker.example.org
Passkey the passkey to use for this host. Blank = leave the stored one unchanged. Clear passkey removes it
Minimum seed hours this tracker requires you to seed. Blank = undeclared (the drain will not delete). 0 = the tracker requires nothing. + Manual host opens with the field blank
Announce auto, v4 only or v6 only

Save writes the three settings to the config file and applies them live. Each torrent picks up a new passkey or IP family at its own next announce, so a change spreads over one interval (30 minutes by default); Reannounce one torrent to check now.

How each setting is matched against a torrent's tracker URLs:

  • Passkey: matches the host itself or any subdomain of it (tracker.example.org also covers announce.tracker.example.org). When several keys match, the longest wins. It is not a substring match. The passkey replaces the last path segment of the URL, so https://tracker.example.org/announce/OLDKEY is announced as https://tracker.example.org/announce/0123456789abcdef. Only a path whose last segment is exactly announce (or empty) is left alone. The query string is kept but not read: https://tracker.example.org/announce.php?passkey=OLD becomes https://tracker.example.org/0123456789abcdef?passkey=OLD, so do not set an override for a tracker that carries its passkey in the query.
  • Announce (IP family): same host-or-subdomain rule. auto sends one announce per address family, with the same peer id, and merges the answers. Pin a host to v4 or v6 if the tracker shows you in only one family. auto is stored as "no entry".
  • Minimum seed: exact host only, and only the host of the torrent's first tracker URL counts. It does not change what is announced: it tells the race drain when a race torrent may be deleted. Blank (undeclared) protects the torrent from deletion; 0 releases it. Details on Race Drain, Graduation and Seed Obligations.

The hint under Host says it: as shown in the Tracker column; passkey and IP family also cover its subdomains.

An engine with enable_ipv6 = false announces over IPv4 only, whatever the host's family says (auto and v6 only included). See Networking.

Mute and Hide

  • Mute keeps the row and drops the tracker out of the red/amber counts and the tab badge (status acknowledged).
  • Hide removes the row from the table and from the badge. The tracker is still announced to. Hidden rows are listed under Hidden trackers, with Unhide per row and Unhide all.
  • Hide unconfigured trackers holding fewer than [10] torrents + Hide them hides every tracker below that count with no passkey and an auto family (the public trackers baked into stray .torrent files). A host with a passkey or an IP family is never hidden this way.

Per-tracker stats

The Per-tracker stats card splits traffic by tracker host and engine (↑ rate, ↓ rate, Peers, Active/Total, Seed size, lifetime ↑ total / ↓ total, Ratio). Tracker chart draws one tracker's upload over time (hoard ↑, race ↑).

The same settings in the config file

The tab writes these tables in default.toml (keys are tracker hosts, values are strings):

[announce_passkeys]
"tracker.example.org" = "0123456789abcdef"

[announce_ip_modes]
"tracker.example.org" = "v4"

[announce_min_seed_hours]
"tracker.example.org" = "72"

[announce_muted] and [announce_hidden] take "tracker.example.org" = "1".

Since 4.4, Config β€Ί Advanced settings (default.toml) can also change existing entries of these five tables (passkeys and IP families under the Trackers & Network sub-tab, the other three under Other; a quoted host key is matched by its bare name). It cannot add a host: use the Trackers tab for that. Such a save answers that a restart is required. Changes made from the Trackers tab or its API routes apply live. Each such save also re-reads the whole file into the running configuration, hand edits included, but restarting is the reliable way to apply a hand edit. Defaults and every other key: Configuration: Daemon, Auth and Global Sections.

The same actions over the REST API (all need the API key, see REST API):

curl -X POST -H "X-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"host":"tracker.example.org","passkey":"0123456789abcdef"}' \
  http://hydranos.example.org:8199/api/announce/passkeys

Same shape for POST /api/announce/ip-modes ({"host","mode":"v4"}) and POST /api/announce/min-seed ({"host","hours":72}). An empty passkey deletes the override; {"host":"…","clear":true} on min-seed makes it undeclared again. POST /api/announce/mute takes {"host","muted"} and POST /api/announce/hidden takes {"host","hidden"} or {"hosts":[…],"hidden":true}. GET /api/trackers returns the tab's rows; GET /api/announce/health and GET /api/announce/errors?host=… return the severities and the error details.

Editing a torrent's trackers

Open a torrent's detail panel. The Trackers card shows:

  • Announced as: the peer id this torrent last announced with, and when (before the first announce: Not announced yet since this engine started and the id it will use). A Next announce line appears only if the next peer id differs, which does not happen in normal use.
  • the table Tracker, Status, Last, Next, Scrape. Status is OK, not announced yet or the error message. Last and Next are the last successful announce and the next due one (or an estimate from the queue right after startup). Scrape shows seeders/leechers (12s/3l), taken from announce answers or, for a torrent no tracker has answered for yet, from a scrape (see Scrape for torrents not announced yet).

These values are the torrent's, not each URL's: every row shows the same, so a dead backup URL looks healthy. The Trackers tab's per-host errors tell them apart.

Edit trackers opens a text box:

  • one URL per line;
  • a blank line starts a new tier. Tiers are tried in order (see Race vs hoard announcing below);
  • accepted schemes: http://, https:// (need a host) and udp:// (needs a host and a port, e.g. udp://tracker.example.org:6969/announce). Anything else is refused with an error. URLs are trimmed, not rewritten;
  • the editor shows which engine's copy you are editing (Engine: race, for example).

Save trackers replaces the whole list (an identical list answers No change to save.). An added tracker gets its own started at the torrent's next announce, not at save time.

Things to know:

  • Survives a restart. Save trackers writes the new list to the engine's resume state at once (see Architecture), and that state wins over the .torrent at startup. The stored .torrent is not rewritten.
  • A torrent added moments ago may refuse an edit with this torrent has no stored .torrent yet; try again a little later.
  • One copy only. If the same torrent is in several engines, the edit applies to the first engine that holds it (race, then hoard, then extra engines).
  • Remote rows: the edit looks up local engines only: it changes the local copy if there is one, and fails with torrent not found otherwise; the node's copy is never edited (see Nodes and Multiple Machines).

Over the REST API:

# Read the live list (also returns engine and peer id state)
curl -H "X-Api-Key: YOUR_API_KEY" \
  http://hydranos.example.org:8199/api/torrents/<info_hash>/trackers

# Add one URL as a new tier
curl -X POST -H "X-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"op":"add","urls":["udp://tracker.example.org:6969/announce"]}' \
  http://hydranos.example.org:8199/api/torrents/<info_hash>/trackers

op is add (each URL in a new tier, duplicates ignored), remove (empty tiers disappear), replace (from β†’ to, error if from is absent) or set (with tiers, an array of arrays). The answer is {"trackers": <tiers>, "changed": true|false}. The qBittorrent shim's torrents/addTrackers and torrents/removeTrackers use the same path (see qBittorrent Shim and Automation).

What a tracker receives

What each engine sends in its announces:

Item Value in 4.4
Peer id -HY and the version, one base-36 character per component (-HY4400- for 4.4.0), followed by 12 random letters and digits. Drawn once per engine at startup: each engine announces its own, and a restart draws a new one
User-Agent Hydranos/4.x.y (the running version)
key 8 hex characters, stable for the life of the process, changes at restart
port the port the engine listens on now (16171 for race, 16172 for hoard by default), a live rebind included; behind a managed WireGuard tunnel, the port the tunnel forwards
uploaded / downloaded counted from zero at each started, never lifetime totals (see What a restart costs your ratio)
left computed from the pieces held
numwant 200 while downloading. Seeding: 0, or 50 in the cases listed under Self-check
compact 1
event started, completed or stopped, or absent for a periodic announce
trackerid echoed back if the tracker sent a tracker id
ip sent only when the engine's announce_ip is set (HTTP ip=, and the UDP ip field for an IPv4 address); empty = not sent, the tracker keeps the source address

An HTTP announce has a 15 s timeout. Hydranos understands interval, min interval, peers / peers6, complete / incomplete, failure reason, warning message (logged), tracker id and BEP 31 retry in.

  • IP family: with auto, one announce leaves per address family; set per host on the Trackers tab.
  • Peer id towards peers: each engine announces and handshakes (incoming and outgoing) with its own peer id, so the peer a tracker lists is the peer that connects.
  • Which network path: an engine's announces leave the way its peers do: pinned to its bind_interface on Linux (or its managed WireGuard tunnel), through its announce_proxy when set, else through its SOCKS5 peer proxy (socks5h://, the tracker's name resolved by the proxy). TYPHON_ANNOUNCE_PROXY is only a fallback for an engine with neither. A proxy URL that does not parse makes the announce fail (announce proxy … is not usable); it never falls back to a direct announce. Details: VPN and Egress and Managed WireGuard.
  • Held announces: an engine held at startup (start_paused) or waiting for its forwarded port (Gluetun, managed WireGuard) announces nothing, and checks again about once a minute.
  • No client spoofing. Hydranos never presents another client's peer id or User-Agent. An old [announce_clients] table is removed at the first start of 4.3 or later, which stops the torrents on those trackers once: start them again after upgrading.

The full request, with each field's specification, is in BITTORRENT-CONFORMANCE.md. Its example shows 4.2.4 (-HY4240-), and three of its passages are outdated in 4.4: BEP 48 "we never scrape" and the section on scrape (see below), and "Magnet links are not resolved" (magnets are resolved).

When Hydranos announces

flowchart LR
    CAT["Catalogue of the engine<br/>re-read every 10 s"] --> ADM["Admission quota<br/>max(total x 10 / 1800, 100) per 10 s"]
    ADM --> Q["Queue per first-tracker host<br/>adaptive concurrency 4 to 2048"]
    BUMP["Events and manual Reannounce"] --> Q
    Q --> HELD{"Engine held?<br/>start_paused or port not known yet"}
    HELD -- "yes, check again in about 1 min" --> Q
    HELD -- "no" --> BRK{"Host breaker open?<br/>5 failures = 10 min pause"}
    BRK -- "yes" --> SKIP["That tracker skipped this pass"]
    SKIP --> RES
    BRK -- "no" --> CLI["HTTP or UDP announce"]
    CLI --> TRK["Tracker"]
    TRK --> RES["Reschedule<br/>interval plus jitter<br/>race refused: 5 s"]
    RES --> Q
Loading
Step Behaviour
Startup the scheduler waits 5 s, then starts announcing
Admission the catalogue joins gradually: each 10 s cycle admits max(total Γ— 10 / 1800, 100) new torrents, spread over one 30-minute interval (under 18,000 torrents the floor of 100 is faster). This is a quota, not a delivery rate: admitted torrents then wait in the per-host queues at each tracker's pace (concurrency, latency, breaker), so on a large catalogue first announces can take far longer than 30 minutes. Until its first announce the detail panel shows not announced yet
Interval the tracker's interval (capped at 7 days), or its min interval when that is larger, for race and hoard alike. Without one, 30 minutes. Any wait under 60 s is raised to 60 s; the race registration retry (5 s, see Race vs hoard announcing) is the only shorter wait
Jitter up to a tenth of the wait, at most 120 s, always added (never early)
min interval a floor per tracker. Scheduled announces never cross it; a Reannounce you request does. An owed completed or stopped goes out regardless of it (see Events)
retry in / Retry-After honoured (capped at 24 h), even by a manual reannounce and by the race registration retry. retry in: never stops that tracker for that torrent until a restart or removal (Stop then Start does not clear it). An owed completed or stopped still goes out before a retry in / Retry-After delay has run out (stopped once, completed retried until accepted), but never to a tracker that answered retry in: never
Adaptive concurrency counted per host of a torrent's first tracker: the torrent holds one slot there for its whole pass, including its other trackers. Each host starts at 32 announces in flight, between 4 and 2048 (4096 per engine in total). It grows while the tracker answers fast, shrinks when latency rises or more than 2 % of answers are 429 or more than 5 % time out. Not configurable
Circuit breaker 5 consecutive failures to one host pause that host for 10 minutes. A 429 or a failure reason counts as an answer, not a failure
Checking nothing is announced while a torrent's data is being checked (retried after 60 s)
Held nothing is announced while the engine is held at startup (start_paused) or waits for its forwarded port; checked again about once a minute (the 60 s floor applies)

Manual reannounce: Reannounce in the context menu of the Race or Hoard list, or:

curl -X POST -H "X-Api-Key: YOUR_API_KEY" \
  http://hydranos.example.org:8199/api/torrents/<info_hash>/reannounce

A manual reannounce crosses a tracker's min interval, but never its retry in / Retry-After. It answers {"status":"ok","bumped":true}, in_flight if an announce is already running, 429 with cooldown and retry_after_secs within 60 s of the previous bump of that torrent (yours, or the one a Stop, Start or completed makes), 429 if the queue is full, 503 if the engine is not announcing, and 202 with "status":"queued","bumped":false if the scheduler did not reply within 5 s. The qBittorrent shim's torrents/reannounce does the same for every copy of the torrent.

A race-role engine comes back sooner than the interval only while a tracker still refuses a torrent it has not registered: see Race vs hoard announcing.

Events

Events are tracked per torrent and per tracker:

sequenceDiagram
    participant U as You
    participant H as Hydranos engine
    participant T as Tracker
    U->>H: Add torrent
    Note over H: boot delay 5 s, then admission<br/>(about 30 min, first announce can be later)
    H->>T: announce event=started
    loop every interval (30 min default, plus jitter)
        H->>T: announce (no event)
    end
    Note over H: download finishes
    H->>T: announce event=completed (right away, retried until delivered)
    U->>H: Stop
    H->>T: announce event=stopped (attempted once)
    U->>H: Start
    H->>T: announce event=started (counters from zero)
    U->>H: Remove
    H->>T: announce event=stopped (attempted once, in the background)
    Note over H,T: clean shutdown: stopped to every tracker that heard started,<br/>race engines first, 5 s at most
Loading
  • started: the first announce of a session to each tracker: after an add, after a restart, after Start, or for a tracker added to the list.

  • completed: owed to every tracker that saw started when the last piece of a download is verified; not sent for a torrent already complete when its session began (seed mode, recheck, cross-seed). Retried at each announce until delivered, but only in memory: a restart before it lands loses it.

  • stopped: sent right away when you Stop a torrent, attempted once per tracker, to every tracker that heard started. Also sent:

    • when a torrent is removed (from the UI, the API, the qBittorrent shim, the race drain, a race purge, a workflow or a share limit): in the background, once per tracker, 20 s at most, with the session counters and the trackerid if one was received;
    • on a clean shutdown (SIGTERM, Restart from the UI or the API, a stop during startup): every engine's started torrents, race-role engines first, 64 at a time, within 5 s in total. What does not leave in time is left to the tracker's own timeout. The log line stopped sent to the trackers gives departed and of;
    • udp:// trackers are skipped when the engine has enable_udp_trackers = false.

    It is also sent when a torrent goes into error because its data disappeared. It then stays silent (nothing re-checks the data) and announces started again only after a Recheck you run finds the data. Torrents that were stopped before a restart do not send a second stopped at boot.

  • Events skip the wait for the next interval: the torrent is queued for an immediate announce (at most once a minute per torrent).

Not implemented in 4.4: a stopped event when a torrent leaves an engine by graduation, a data move (move_data job) or Move to engine β€Ί, or when Hydranos crashes or is killed β€” the tracker simply stops hearing from that peer and times the entry out β€” if a tracker needs a clean departure, Stop the torrent and wait for the announce first.

What a restart costs your ratio

The uploaded a tracker receives is a session total, counted from that session's started. Hydranos reports uploaded only at announces, and a new session (started, counters from zero) begins after every restart. A remove and a clean shutdown send stopped with the session counters, so that upload is reported. It is not reported (worst case one interval, 30 minutes by default, of upload per torrent and tracker) after a crash or kill, a graduation, a data move or Move to engine β€Ί (those re-add the torrent elsewhere without stopped), or at shutdown for whatever did not leave within the 5 s budget. Hydranos' own lifetime counters are not affected. On a very large catalogue, Stop the torrents that matter and wait for their announces before a planned shutdown.

Race vs hoard announcing

The engine's role decides how far down the tracker list a pass goes:

Race-role engine Hoard-role engine
Trackers per pass every tracker of every tier trackers in tier order, stopping at the first that answers (BEP 12)
Refused torrent retried every 5 s while still downloading, no tracker has accepted it and at least one answered with a failure reason (any reason, bad passkey included), for registration_retry_minutes (6 by default: at most 72 refusals per tracker); not in a pass where a tracker timed out or answered 429. A retry in / Retry-After still holds it back no special retry
Once accepted the tracker's interval the tracker's interval

This covers the race case where the .torrent arrives before the tracker has registered the upload. The retry window is set per engine in its section ([race], or an extra race-role engine's), read when the engine starts (restart to change it), with no field in the UI:

[race]
registration_retry_minutes = 6

0 (or absent) means the default, 6 minutes, not "off". The refusal count stops at 255, so anything above about 21 minutes behaves as 21. The key has no effect on a hoard-role engine. More on roles: Engines: Race and Hoard.

UDP trackers

udp:// trackers are announced to (BEP 15, with BEP 41 so the path and passkey reach the tracker).

  • Switch per engine: enable_udp_trackers in [race], [hoard] or an extra engine's session table. Absent means on. Read at engine start. When off, udp:// URLs are skipped silently.
  • One UDP client for the default route, plus one per interface an engine is pinned to: an engine's UDP announces leave from its bind_interface (or its managed WireGuard tunnel), like its HTTP ones.
  • Connect and announce are each tried twice (3 s, then 5 s), then the next announce retries, under the same breaker and floors as HTTP. UDP answers have no min interval; an interval of 0 means 30 minutes.
  • When the engine's announces go through a proxy (its announce_proxy, its SOCKS5 peer proxy, or the TYPHON_ANNOUNCE_PROXY fallback), UDP announces are not sent: they fail with UDP trackers do not go through a SOCKS5 proxy (no UDP ASSOCIATE): they will not be announced while this proxy is active, class udp_proxied (shown as that sentence in the Trackers tab's Errors (1h) cell), so the tracker never sees your real address beside the proxy (see VPN and Egress).

Scrape for torrents not announced yet

Seeder and leecher counts (the Scrape column, the swarm columns of the lists, the qBittorrent shim's num_seeds / num_complete / num_incomplete, the num_seeds, swarm_seeds and swarm_leechers fields of Workflows) come from the complete / incomplete fields of announce answers, refreshed at each announce. A torrent no tracker has answered for yet (waiting in the queue after startup, or stopped) would show zeros; since 4.4 a scrape (BEP 48 over HTTP, BEP 15 over UDP) fills those counts, and only those.

flowchart LR
    START["Engine starts"] --> WAIT["90 s"]
    WAIT --> HELD{"Engine held?<br/>start_paused"}
    HELD -- "yes" --> SLEEP["Wait 300 s"]
    HELD -- "no" --> PICK["Up to 5000 torrents with no announce answer,<br/>not scraped in the last hour"]
    PICK --> TGT["First scrapable tracker in tier order<br/>whose host breaker is closed"]
    TGT --> REQ["50 hashes per request, 2 s apart per tracker,<br/>8 trackers at once"]
    REQ --> FILL["Seeders and leechers written,<br/>unless an announce answered meanwhile"]
    FILL --> SLEEP
    SLEEP --> HELD
Loading
  • One loop per engine, beside its announcer. Not configurable and cannot be turned off; no key exists.
  • Which URL: for HTTP, the last path segment must start with announce, which becomes scrape (https://tracker.example.org/announce.php?passkey=X β†’ https://tracker.example.org/scrape.php?passkey=X; the query is kept); any other path is not scraped. The passkey override of the Trackers tab applies. A udp:// tracker is scraped unless enable_udp_trackers = false.
  • Which path: the same as the engine's announces: its interface, its proxy, nothing while the engine is held at startup (start_paused) (an engine that only waits for its forwarded port does scrape: a scrape carries no port), nothing to a host whose breaker is open, no UDP scrape behind a proxy.
  • What it does not do: it never counts as an announce. Nothing that waits for a first announce (the scheduler, the race timeline, the Trackers tab's rows and errors) sees it; it starts and stops nothing. A torrent already announced is never scraped. The first error from a tracker ends that tracker's turn; the torrents it did not get to are scraped again after an hour at the earliest.
  • One INFO log line per pass that had torrents to scrape: scrape: swarm counts for torrents not announced yet with filled.

Adding trackers in bulk

No context-menu bulk edit exists. Use a workflow with the add trackers action (add_trackers): announce URLs and/or the URL of a list to fetch (one per line, fetched at most daily, 500 URLs and 1 MiB max), each in a new tier. It never touches a private torrent. See Workflows.

Troubleshooting

Symptom Likely cause
Row says not announced long after startup the torrent is stopped, the engine is held (start_paused, or a forwarded port not known yet), or its first announce still waits in the per-host queue after admission (admission ends within about 30 min; on a large catalogue the first announce can come much later). The Scrape column may already show counts: they come from a scrape, not an announce
needs action with invalid_passkey wrong passkey: set it in Edit, then Reannounce one torrent to check
Passkey saved but URL unchanged the URL ends in /announce; edit the torrent's tracker URL instead
needs action after setting a passkey the tracker carries its passkey in the query string: the override replaced a path segment. Remove the override
UDP tracker never answers the engine's announces go through a proxy (error class udp_proxied), enable_udp_trackers = false, or the URL has no port

More: Troubleshooting. Announce figures and logs (announce failed, tracker warning): Monitoring and Logs.

⚠️ **GitHub.com Fallback** ⚠️