alibaba/open-code-review · error
read tools file %s: %w
Error message
read tools file %s: %w
What it means
Load reads tool definitions either from the built-in defaultToolsJSON (path=="") or from the file at the given path; this error wraps os.ReadFile failures for a custom path. It means the tools config file could not be read at all — not that its contents are invalid.
Source
Thrown at internal/config/toolsconfig/toolsconfig.go:35
PlanTask bool `json:"plan_task"`
MainTask bool `json:"main_task"`
Definition json.RawMessage `json:"definition"`
}
//go:embed tools.json
var defaultToolsJSON []byte
// Load parses the tools config file. When path is empty, falls back to
// the embedded default tools configuration.
func Load(path string) ([]ToolConfigEntry, error) {
var data []byte
var err error
if path == "" {
data = defaultToolsJSON
} else {
data, err = os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read tools file %s: %w", path, err)
}
}
var tools []ToolConfigEntry
if err := json.Unmarshal(data, &tools); err != nil {
return nil, fmt.Errorf("unmarshal tools file: %w", err)
}
return tools, nil
}
// ToolDefsByPhase returns the parsed tool definitions filtered by phase.
// planOnly=true returns only tools with plan_task:true.
// planOnly=false returns only tools with main_task:true.
func (t *ToolConfigEntry) ToolDefsByPhase(planOnly bool) (json.RawMessage, bool) {
switch {
case planOnly && t.PlanTask:
return t.Definition, true
case !planOnly && t.MainTask:
return t.Definition, trueView on GitHub (pinned to 5cf97d0d15)
Solutions
- Verify the path exists and is a readable file (ls/ll the path), or pass an absolute path
- Pass an empty path to fall back to the built-in default tools JSON
- Fix filesystem permissions for the user running the tool
Example fix
// before
tools, err := toolsconfig.Load("./tools.json") // file missing
// after
path := "./tools.json"
if _, err := os.Stat(path); err != nil { path = "" } // fall back to defaults
tools, err := toolsconfig.Load(path) Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(path)
if err != nil || info.IsDir() { return fmt.Errorf("tools file %s unavailable: %w", path, err) } Try / catch
tools, err := toolsconfig.Load(path)
if err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) { tools, err = toolsconfig.Load("") /* defaults */ }
if err != nil { return err }
} Prevention
- Resolve tools-file paths to absolute at CLI flag parsing time
- Fall back to the embedded default tools when no path is usable
- Check file readability for the effective user in service/CI contexts
When it happens
Trigger: Calling Load(path) with a non-empty path where os.ReadFile fails: file does not exist, permission denied, path is a directory, or an I/O error.
Common situations: Passing a --tools flag with a wrong/relative path from a different working directory; the tools file was deleted or renamed; running under a service account lacking read permission.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- read app config %s: %w
- unmarshal tools file: %w
- resolve OCR config file: %w
- resolve %s: %w
- load config: %w
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/d809b1eae27077eb.
Report an issue: GitHub.