AlistGo/alist · error
missing cookie or qrcode account
Error message
missing cookie or qrcode account
What it means
This is the error path in alist's custom ServeHTTP (internal/net/serve.go) for a plain, non-Range download. When the client sends no Range header (or the ranges were discarded), the server asks the storage driver for the whole file via RangeReadCloser.RangeRead(ctx, http_range.Range{Length: -1}); if the driver cannot produce a reader, the raw driver error text is written to the client with HTTP 416 (Requested Range Not Satisfiable), or 429 if the error is net.ErrExceedMaxConcurrency. The 416 status here is a code smell: it has nothing to do with ranges, it simply reuses the 'cannot open reader' status.
Source
Thrown at drivers/115/util.go:75
}
d.client = driver115.New(opts...)
cr := &driver115.Credential{}
if d.QRCodeToken != "" {
s := &driver115.QRCodeSession{
UID: d.QRCodeToken,
}
if cr, err = d.client.QRCodeLoginWithApp(s, driver115.LoginApp(d.QRCodeSource)); err != nil {
return errors.Wrap(err, "failed to login by qrcode")
}
d.Cookie = fmt.Sprintf("UID=%s;CID=%s;SEID=%s;KID=%s", cr.UID, cr.CID, cr.SEID, cr.KID)
d.QRCodeToken = ""
} else if d.Cookie != "" {
if err = cr.FromCookie(d.Cookie); err != nil {
return errors.Wrap(err, "failed to login by cookies")
}
d.client.ImportCredential(cr)
} else {
return errors.New("missing cookie or qrcode account")
}
return d.client.LoginCheck()
}
func (d *Pan115) getFiles(fileId string) ([]FileObj, error) {
res := make([]FileObj, 0)
if d.PageSize <= 0 {
d.PageSize = driver115.FileListLimit
}
limit := d.PageSize
if limit > driver115.MaxDirPageLimit {
limit = driver115.MaxDirPageLimit
}
opts := driver115.DefaultListOptions()
driver115.WithMultiUrls()(opts)
if len(opts.ApiURLs) == 0 {
opts.ApiURLs = []string{driver115.ApiFileList}View on GitHub (pinned to 843d9dc814)
Solutions
- Read the response body: it contains the underlying driver error (err.Error()), which names the real cause (auth failure, 404, network timeout) — fix that first.
- If the body says 'ExceedMaxConcurrency' (HTTP 429), reduce parallel connections/streams in the client or alist settings, or raise the concurrency limit for the driver/downloader.
- Re-test with curl -v <url> without a Range header to confirm the failure is specific to full-file reads vs range reads.
- If the error mentions expired links/tokens, refresh the driver token or clear the cached direct link and retry.
- If the error persists across all files for one mount, verify the storage driver credentials and remote reachability in the alist admin UI.
Example fix
// before: hammering the URL with many parallel full downloads
for i := 0; i < 20; i++ {
go http.Get(url) // some responses come back 429 ExceedMaxConcurrency
}
// after: limit concurrency to the server's budget and honor 429
sem := make(chan struct{}, 4)
for i := 0; i < 20; i++ {
sem <- struct{}{}
go func() {
defer func() { <-sem }()
resp, err := http.Get(url)
if err == nil && resp.StatusCode == http.StatusTooManyRequests {
time.Sleep(time.Second * time.Duration(1+rand.Intn(3)))
// retry once
}
}()
} Defensive patterns
Strategy: retry
Validate before calling
// Before downloading, verify the backend can produce a reader cheaply:
// issue a 1-byte range probe; full-file reads share the same failure modes.
req, _ := http.NewRequest("GET", fileURL, nil)
req.Header.Set("Range", "bytes=0-0")
resp, err := http.DefaultClient.Do(req)
if err != nil || resp.StatusCode >= 400 {
// backend not ready / link expired / concurrency full: don't start the full download
return fmt.Errorf("backend not readable: status=%d", resp.StatusCode)
} Prevention
- Treat HTTP 416 on a NON-range request from alist as a backend failure, not a range problem — always log the body, it carries the driver error.
- Honor 429 with backoff; it means the global download concurrency limit is exhausted.
- Keep driver credentials fresh and clear cached direct links after token rotation.
- Cap client-side parallel connections below alist's configured concurrency limit.
When it happens
Trigger: Calling GET/HEAD on a proxied or streamed file (no 'Range: bytes=...' header) where the backend RangeReadCloser fails: storage driver link-fetch returns an error (expired token, 404 on the remote), the remote server is unreachable, credentials are invalid, or the download concurrency limit is exhausted so downloader.download() returns ErrExceedMaxConcurrency (internal/net/request.go:122) and the response becomes 429 Too Many Requests.
Common situations: Direct-link/proxy downloads from cloud drive drivers (Google Drive, OneDrive, etc.) after the cached link expires; misconfigured driver credentials after password change; reverse proxies with many parallel connections hitting the global concurrency limit; remote quota/rate-limit responses surfacing as raw error bodies; disk-driver failures (file deleted at the storage side).
Related errors
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/48f77416cb867601.
Report an issue: GitHub.