AlistGo/alist · warning

cannot download a submodule

Error message

cannot download a submodule

What it means

Link() refuses to produce a download link when the fetched object's type is 'submodule': a git submodule entry points at a commit SHA in another repository, and the GitHub contents/raw API cannot serve it as a file. The driver surfaces this as an explicit, user-facing restriction instead of returning a broken URL.

Source

Thrown at drivers/github/driver.go:174

		return ret, nil
	} else {
		ret := make([]model.Obj, 0, len(obj.Entries))
		for _, entry := range obj.Entries {
			if entry.Name != ".gitkeep" {
				ret = append(ret, entry.toModelObj())
			}
		}
		return ret, nil
	}
}

func (d *Github) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
	obj, err := d.get(file.GetPath())
	if err != nil {
		return nil, err
	}
	if obj.Type == "submodule" {
		return nil, errors.New("cannot download a submodule")
	}
	url := obj.DownloadURL
	ghProxy := strings.TrimSpace(d.Addition.GitHubProxy)
	if ghProxy != "" {
		url = strings.Replace(url, "https://raw.githubusercontent.com", ghProxy, 1)
	}
	return &model.Link{
		URL: url,
	}, nil
}

func (d *Github) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
	if !d.isOnBranch {
		return errors.New("cannot write to non-branch reference")
	}
	d.commitMutex.Lock()
	defer d.commitMutex.Unlock()
	parent, err := d.get(parentDir.GetPath())

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Do not download submodule entries through this mount; clone the repo with 'git clone --recurse-submodules' instead.
  2. If submodules are noise, ignore them in listings or hide them with the driver/front-end filter options.
  3. There is no driver-side fix — the raw API genuinely has no blob for a submodule pointer.
Defensive patterns

Strategy: type-guard

Validate before calling

obj, err := d.get(file.GetPath())
if err != nil { return nil, err }
if obj.Type == "submodule" {
    return nil, errors.New("cannot download a submodule")
}

Type guard

func isSubmodule(obj *TreeObj) bool {
    return obj != nil && obj.Type == "submodule"
}

Try / catch

link, err := d.Link(ctx, file, args)
if err != nil && err.Error() == "cannot download a submodule" {
    // skip in UI / guide user to git clone --recurse-submodules
}

Prevention

When it happens

Trigger: Clicking/downloading a directory entry whose tree type is 'submodule' (a .gitmodules entry) in a mounted GitHub repo. drivers/github/driver.go:174.

Common situations: Repos vendoring dependencies as submodules (common in C/C++ projects); users browsing a repo through OpenList and trying to download the submodule folder like a normal directory.

Related errors


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