AlistGo/alist · error

failed to get download link

Error message

failed to get download link

What it means

In Link() with WebProxy enabled, the driver probes the Feishu download endpoint with a 'Range: bytes=0-1' request and expects 206 Partial Content as proof the URL+Bearer token yield a working download. Any other status after the one retry-with-forced-refresh falls here. It is a link-validation failure: the returned model.Link would be broken, so none is returned.

Source

Thrown at drivers/lark/driver.go:407

			return nil, err
		}
		_ = ar.Body.Close()

		if isHTTPAuthFailed(ar.StatusCode) && strings.TrimSpace(c.RefreshToken) != "" {
			accessToken, err = c.downloadAccessToken(ctx, true)
			if err != nil {
				return nil, err
			}
			req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
			ar, err = http.DefaultClient.Do(req)
			if err != nil {
				return nil, err
			}
			_ = ar.Body.Close()
		}

		if ar.StatusCode != http.StatusPartialContent {
			return nil, errors.New("failed to get download link")
		}

		return &model.Link{
			URL: url,
			Header: http.Header{
				"Authorization": []string{fmt.Sprintf("Bearer %s", accessToken)},
			},
		}, nil
	}

	return nil, errors.New("lark download requires web proxy")
}

func (c *Lark) filePreviewURL(token string) string {
	prefix := strings.TrimRight(strings.TrimSpace(c.TenantUrlPrefix), "/")
	if prefix == "" {
		prefix = "https://www.feishu.cn"
	}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Check the actual status: temporarily log ar.StatusCode before the guard to identify 401/403/400
  2. For native doc types, use the export flow (createExportTask) instead of direct download
  3. Re-grant app/user permissions (drive:file:download scope) and refresh tokens
  4. Ensure the token used is a user access token with access to that specific file

Example fix

// before
if ar.StatusCode != http.StatusPartialContent {
	return nil, errors.New("failed to get download link")
}
// after (diagnosable failure)
if ar.StatusCode != http.StatusPartialContent {
	return nil, fmt.Errorf("failed to get download link: probe status=%d", ar.StatusCode)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if !c.WebProxy {
	return nil, errors.New("enable web proxy on the lark storage to download files")
}

Try / catch

link, err := c.Link(ctx, file, args)
if err != nil && err.Error() == "failed to get download link" {
	// probe failed (401/403/400): check permission and file type, then surface clearly
	return nil, fmt.Errorf("feishu refused download for %s (permission or unsupported type): %w", file.GetPath(), err)
}

Prevention

When it happens

Trigger: GET open.feishu.cn/open-apis/drive/v1/files/{token}/download returns non-206 — 403 (no permission on the file), 400 (file type not downloadable, e.g. native docs), 401 twice (both tokens rejected), or a redirect/login HTML page from a non-API gateway.

Common situations: User lacks download permission on the shared file; trying to 'download' a Feishu doc/sheet/bitable native file (needs export flow instead); expired download scope on the app token.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/7792f7b8e7bfe6c3. Report an issue: GitHub.