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

  1. 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.
  2. 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.
  3. Re-test with curl -v <url> without a Range header to confirm the failure is specific to full-file reads vs range reads.
  4. If the error mentions expired links/tokens, refresh the driver token or clear the cached direct link and retry.
  5. 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

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.