gotd / gotd/cli

download hangs forever on cross-datacenter files (zero-byte output, no error)

Open
#275 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
34
Forks
6
PR merge metrics
No merged PRs in 30d

Description

Summary

tg download hangs forever, writes a zero-byte file and prints no error whenever
the file lives on a datacenter other than the account's home DC. In practice that
is most media, since a file's DC frequently differs from the account's.

Reproduced on v0.11.0, macOS arm64, against a real account (home DC 4, file on
DC 5), on two different photos.

$ tg download @somechannel 1073 --out ./dl/
<hangs indefinitely>
$ ls -la dl/
-rw-r--r--  0 photo_6136248896133469079.jpg

Cause

Not in this repo. floodwait.Waiter's send loop calls Invoke synchronously, so
it cannot dispatch anything else until that call returns. FILE_MIGRATE is the
one path where gotd/td starts an invoke from inside an in-flight invoke:

upload.getFile                      -> FILE_MIGRATE_5
  telegram/invoke.go  invokeDirect  -> invokeSub(targetDC)
    telegram/pool.go  dc            -> createPool
      telegram/transfer.go transfer -> auth.exportAuthorization

exportAuth goes through c.invoker, the middleware-wrapped invoker, so it
re-enters Waiter.Handle while the send loop is still blocked on
upload.getFile. The nested call can never be scheduled; the outer call can
never return. Neither errors, so there is nothing to log.

With zap at debug level the trace stops dead:

Got error   err_code=303  err_msg=FILE_MIGRATE_5
telegram/invoke.go:71  Invoking on target DC  target_dc=5
telegram/pool.go:75    Creating pool  dc_id=5  max=1
<no dial, no error, no further traffic>

Ruled out along the way: network (all DCs reachable on 443), transport
(TDesktopResolver and gotd's default behave identically), rate limiting (the
flood-wait callback never fires), and chunk size (512/128/64/32 KiB all hang).

Fix

gotd/contrib#773 makes the waiter handle re-entrant invokes. With that branch,
unmodified gotd/cli v0.11.0 downloads the same photo in 4.1 seconds. No
change is needed in this repo once it lands and is released.

If an interim fix is wanted here before then, swapping floodwait.NewWaiter()
for floodwait.NewSimpleWaiter().WithMaxWait(time.Minute).WithMaxRetries(5) in
cmd/tg/app.go also resolves it, since SimpleWaiter retries inline and is
re-entrant. That trades away global flood coordination, so the contrib fix is
the better one. Happy to send either as a PR if useful.

Unrelated, smaller

While testing, download leaves its zero-byte output file behind on failure.
Worth deleting a partial file on error regardless of this bug, since an empty
file is indistinguishable from a slow network.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by checking gotd/contrib#773 and whether its re-entrant waiter fix is released, since the issue says no repository change is needed afterward. If an interim fix is preferred, inspect cmd/tg/app.go around floodwait.NewWaiter and verify a cross-datacenter download completes; also consider the separately noted zero-byte cleanup on failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.