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
- List valid names via tool.Tools.Names() (or the API endpoint that exposes them) and use an exact match
- Correct spelling/casing of the tool name in the request
- 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
- Always source tool names from tool.Tools.Names(), never hardcode them
- Treat tool names as case-sensitive identifiers, not display labels
- Validate the name at the API boundary before touching the registry
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
- {message}
- same-name files cannot offline download
- directory separator prohibited
- name token must come before chunk token
- pattern must contain one name token: {name}
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/82c8ba43fa1a4603.
Report an issue: GitHub.