alibaba/open-code-review · error

unmarshal tools file: %w

Error message

unmarshal tools file: %w

What it means

Load successfully read the tools JSON but json.Unmarshal could not decode it into []ToolConfigEntry; the error wraps the decode failure. This indicates the file is malformed JSON or its structure does not match the expected array of tool entries.

Source

Thrown at internal/config/toolsconfig/toolsconfig.go:40

//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, true
	default:
		return nil, false
	}
}

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Run the file through a JSON validator and fix syntax errors
  2. Compare the file structure against []ToolConfigEntry and fix field names/types
  3. Start from the built-in default tools JSON (pass empty path) and re-apply customizations

Example fix

// before
[{"name":"read_files","enabled":"yes"}] // wrong type
// after
[{"name":"read_files","enabled":true}]
Defensive patterns

Strategy: validation

Validate before calling

var probe []toolsconfig.ToolConfigEntry
if err := json.Unmarshal(data, &probe); err != nil { return err } // pre-check before Load

Try / catch

tools, err := toolsconfig.Load(path)
if err != nil {
    var typeErr *json.UnmarshalTypeError
    if errors.As(err, &typeErr) { return fmt.Errorf("tools schema mismatch at %s: %w", typeErr.Field, err) }
    return err
}

Prevention

When it happens

Trigger: Calling Load() (default bytes) or Load(path) where the JSON is syntactically invalid, is not an array, or entries have fields with mismatched types (e.g. string where bool expected).

Common situations: Hand-edited tools file with a trailing comma or unquoted key; a tools file written for an older schema version whose fields changed types; someone saved a YAML file with a .json extension.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/ae5a1429156da9cd. Report an issue: GitHub.