{"record":{"id":"ae65743545517313","repo":"wavetermdev/waveterm","slug":"missing-edits-parameter","errorCode":null,"errorMessage":"missing edits parameter","messagePattern":"missing edits parameter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/tools_builder.go","lineNumber":167,"sourceCode":"}\n\ntype builderEditAppFileParams struct {\n\tEdits []fileutil.EditSpec `json:\"edits\"`\n}\n\nfunc parseBuilderEditAppFileInput(input any) (*builderEditAppFileParams, error) {\n\tresult := &builderEditAppFileParams{}\n\n\tif input == nil {\n\t\treturn nil, fmt.Errorf(\"input is required\")\n\t}\n\n\tif err := utilfn.ReUnmarshal(result, input); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid input format: %w\", err)\n\t}\n\n\tif len(result.Edits) == 0 {\n\t\treturn nil, fmt.Errorf(\"missing edits parameter\")\n\t}\n\n\treturn result, nil\n}\n\nfunc formatEditDescriptions(edits []fileutil.EditSpec) []string {\n\tnumEdits := len(edits)\n\teditStr := \"edits\"\n\tif numEdits == 1 {\n\t\teditStr = \"edit\"\n\t}\n\n\tresult := make([]string, len(edits)+1)\n\tresult[0] = fmt.Sprintf(\"editing app.go (%d %s)\", numEdits, editStr)\n\n\tfor i, edit := range edits {\n\t\tnewLines := len(strings.Split(edit.NewStr, \"\\n\"))\n\t\toldLines := len(strings.Split(edit.OldStr, \"\\n\"))","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/tools_builder.go#L149-L185","documentation":"Input unmarshaled into builderEditAppFileParams successfully, but the Edits slice is empty (len == 0). An edit tool call with no edits is a no-op, so it's rejected as missing the required parameter, prompting the caller to supply at least one find/replace edit.","triggerScenarios":"Tool called with {} or {\"edits\": []} — edits key missing or an empty array supplied.","commonSituations":"Model deciding nothing needs changing but still calling the tool; a loop that exhausts edits before invoking; client code building an empty edits slice by mistake.","solutions":["Include at least one edit object: {\"edits\": [{\"find\": \"old\", \"replace\": \"new\"}]}","Skip the tool call entirely in caller logic when no edits are pending","Add prompt/tool-description guidance that edits must contain one or more find/replace entries"],"exampleFix":"// before\n{\"edits\": []}\n// after\n{\"edits\": [{\"find\": \"foo\", \"replace\": \"bar\"}]}","handlingStrategy":"validation","validationCode":"if m, ok := input.(map[string]any); ok { if e, _ := m[\"edits\"].([]any); len(e) == 0 { return errors.New(\"edits must contain at least one entry\") } }","typeGuard":"func hasEdits(input any) bool { m, ok := input.(map[string]any); if !ok { return false }; e, ok := m[\"edits\"].([]any); return ok && len(e) > 0 }","tryCatchPattern":"params, err := parseBuilderEditAppFileInput(input); if err != nil && strings.Contains(err.Error(), \"missing edits\") { return fmt.Errorf(\"no-op edit rejected: %w\", err) }","preventionTips":["Only call the edit tool when at least one find/replace is pending","Skip the call and return early when the edits list is empty","State in the tool description that edits must be a non-empty array"],"tags":["tool-input","missing-parameter","builder-tools"],"backgroundTag":"missing-required-argument","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}