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
- Check the actual status: temporarily log ar.StatusCode before the guard to identify 401/403/400
- For native doc types, use the export flow (createExportTask) instead of direct download
- Re-grant app/user permissions (drive:file:download scope) and refresh tokens
- 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
- Check file permissions and downloadable file type before requesting links
- For native docs route to the export flow rather than Link()
- Patch the guard to include the probe status code so triage needs no reproduction
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
- lark download requires web proxy
- lark refresh token expired
- lark refresh token response missing access token
- lark tenant access token is empty
- lark file token not found
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/7792f7b8e7bfe6c3.
Report an issue: GitHub.