AlistGo/alist · error
empty download url
Error message
empty download url
What it means
During Link() the driver had a cached *Object whose DownloadURL was empty, so it re-fetched the file content via the Gitee contents API; the fresh response also had an empty DownloadURL, meaning Gitee did not supply a raw-file link for this path. The driver refuses to return a link that cannot be downloaded.
Source
Thrown at drivers/gitee/driver.go:90
objs := make([]model.Obj, 0, len(contents))
for i := range contents {
objs = append(objs, contents[i].toModelObj())
}
return objs, nil
}
func (d *Gitee) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
var downloadURL string
if obj, ok := file.(*Object); ok {
downloadURL = obj.DownloadURL
if downloadURL == "" {
relPath := d.relativePath(file.GetPath())
content, err := d.getContent(relPath)
if err != nil {
return nil, err
}
if content.DownloadURL == "" {
return nil, errors.New("empty download url")
}
obj.DownloadURL = content.DownloadURL
downloadURL = content.DownloadURL
}
} else {
relPath := d.relativePath(file.GetPath())
content, err := d.getContent(relPath)
if err != nil {
return nil, err
}
if content.DownloadURL == "" {
return nil, errors.New("empty download url")
}
downloadURL = content.DownloadURL
}
url := d.applyProxy(downloadURL)
return &model.Link{
URL: url,View on GitHub (pinned to 843d9dc814)
Solutions
- Verify the access token is configured and has read access to the private repo (contents API then returns download_url).
- Check whether the file is empty or an LFS pointer; if so, download via git or configure LFS handling rather than the raw URL.
- Re-list the directory so the cached Object is refreshed from a current API response.
- If the API response shape changed, update the Content struct mapping in the driver.
Defensive patterns
Strategy: try-catch
Validate before calling
if obj, ok := file.(*Object); ok && obj.DownloadURL != "" {
// fast path: no API call needed
return &model.Link{URL: d.applyProxy(obj.DownloadURL)}, nil
} Type guard
func hasDownloadURL(o model.Obj) bool {
if obj, ok := o.(*Object); ok {
return obj.DownloadURL != ""
}
return false
} Try / catch
link, err := d.Link(ctx, file, args)
if err != nil && err.Error() == "empty download url" {
// refresh listing and retry once
op.RefreshDir(ctx, parentPath)
link, err = d.Link(ctx, file, args)
} Prevention
- Keep directory listings fresh so cached objects carry download URLs.
- Always configure a token for private repos.
- Treat empty/LFS files specially before requesting links.
When it happens
Trigger: Calling Link() on a file whose *Object.DownloadURL is empty AND whose GET /repos/{owner}/{repo}/contents/{path} response has an empty download_url — typical for empty files, LFS-pointer files, files in private repos with no token, or unsupported content encodings. drivers/gitee/driver.go:90.
Common situations: Zero-byte file where Gitee omits download_url; private repository accessed without an access token so the contents API returns limited fields; file stored with Git LFS where the API returns a pointer instead of a blob URL; API change in the contents response shape.
Related errors
- server returns no url
- cannot download a submodule
- missing cookie or qrcode account
- owner and repo are required
- invalid response
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/dd1103a1fb16dc9b.
Report an issue: GitHub.