AlistGo/alist · error

tool %s not found

Error message

tool %s not found

What it means

ToolsManager.Get() looks up an offline-download tool by name in a registry populated by each package's init() (115, 123_open, guangyapan, http, pikpak, thunder, transmission, aria2/qbit via their own registrations). An unknown name — before any availability check like IsReady — returns this error. It almost always means the requested tool name does not match a registered tool.

Source

Thrown at internal/offline_download/tool/tools.go:19

package tool

import (
	"fmt"
	"github.com/alist-org/alist/v3/internal/model"
	"sort"
)

var (
	Tools = make(ToolsManager)
)

type ToolsManager map[string]Tool

func (t ToolsManager) Get(name string) (Tool, error) {
	if tool, ok := t[name]; ok {
		return tool, nil
	}
	return nil, fmt.Errorf("tool %s not found", name)
}

func (t ToolsManager) Add(tool Tool) {
	t[tool.Name()] = tool
}

func (t ToolsManager) Names() []string {
	names := make([]string, 0, len(t))
	for name := range t {
		if tool, err := t.Get(name); err == nil && tool.IsReady() {
			names = append(names, name)
		}
	}
	sort.Strings(names)
	return names
}

func (t ToolsManager) Items() []model.SettingItem {

View on GitHub (pinned to 843d9dc814)

Solutions

  1. List valid names via tool.Tools.Names() (or the API endpoint that exposes them) and use an exact match
  2. Correct spelling/casing of the tool name in the request
  3. If a driver is missing, build the binary with that driver package included / use the full build

Example fix

// before
name := "picpak"
tool, err := tool.Tools.Get(name)

// after
name := "pikpak"
if _, err := tool.Tools.Get(name); err != nil {
    log.Fatalf("unknown tool %q, available: %v", name, tool.Tools.Names())
}
Defensive patterns

Strategy: validation

Validate before calling

names := tool.Tools.Names() // only ready tools
if !slices.Contains(names, name) {
    return fmt.Errorf("tool %q not found; available: %v", name, names)
}
t, err := tool.Tools.Get(name)

Type guard

func isValidToolName(name string) bool {
    _, ok := tool.Tools[name]
    return ok
}

Try / catch

t, err := tool.Tools.Get(name)
if err != nil {
    return fmt.Errorf("%w (available: %v)", err, tool.Tools.Names())
}

Prevention

When it happens

Trigger: Passing a 'tool' field in the offline download API that is not a registered name: misspellings ('picpak'), wrong casing ('Thunder' vs 'thunder'), or a tool package excluded from the build.

Common situations: Typos in API clients or scripts; using the tool's display name instead of its registered Name(); forks that compile out driver packages (some drivers are behind build tags or split binaries).

Related errors


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