{"record":{"id":"072be689f2cf4bc7","repo":"wavetermdev/waveterm","slug":"offset-must-be-non-negative-got-d","errorCode":null,"errorMessage":"offset must be non-negative, got %d","messagePattern":"offset must be non-negative, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/tools_readfile.go","lineNumber":62,"sourceCode":"\t\treturn nil, fmt.Errorf(\"missing filename parameter\")\n\t}\n\n\tif result.Origin == nil {\n\t\torigin := \"start\"\n\t\tresult.Origin = &origin\n\t}\n\n\tif *result.Origin != \"start\" && *result.Origin != \"end\" {\n\t\treturn nil, fmt.Errorf(\"invalid origin value '%s': must be 'start' or 'end'\", *result.Origin)\n\t}\n\n\tif result.Offset == nil {\n\t\toffset := 0\n\t\tresult.Offset = &offset\n\t}\n\n\tif *result.Offset < 0 {\n\t\treturn nil, fmt.Errorf(\"offset must be non-negative, got %d\", *result.Offset)\n\t}\n\n\tif result.Count == nil {\n\t\tcount := ReadFileDefaultLineCount\n\t\tresult.Count = &count\n\t}\n\n\tif *result.Count < 1 {\n\t\treturn nil, fmt.Errorf(\"count must be at least 1, got %d\", *result.Count)\n\t}\n\n\tif result.MaxBytes == nil {\n\t\tmaxBytes := ReadFileDefaultMaxBytes\n\t\tresult.MaxBytes = &maxBytes\n\t}\n\n\treturn result, nil\n}","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/tools_readfile.go#L44-L80","documentation":"The \"offset\" parameter is a line offset and must be zero or positive. Negative offsets have no defined meaning (no backward seeking past start), so parseReadTextFileInput rejects them before reading.","triggerScenarios":"Passing {\"offset\": -1} or any negative integer, e.g. when an agent computes offset = matchLine - N without clamping at 0.","commonSituations":"Paging backwards from a match near the top of a file; arithmetic on line numbers producing negatives; copying offset semantics from byte-based APIs that allow negatives.","solutions":["Clamp offset to >= 0 before the call (Math.max(0, offset)).","Omit \"offset\" to read from the start (defaults to 0).","Use origin \"end\" with a non-negative offset to read from the tail instead of negative math."],"exampleFix":"// before\n{\"filename\": \"/tmp/a.txt\", \"offset\": -5}\n// after\nconst offset = Math.max(0, want - 5);\nread_text_file({\"filename\": \"/tmp/a.txt\", \"offset\": offset})","handlingStrategy":"validation","validationCode":"const safeOffset = Number.isInteger(offset) && offset >= 0 ? offset : 0;","typeGuard":"func validOffset(o int) bool { return o >= 0 }","tryCatchPattern":"params, err := parseReadTextFileInput(input)\nif err != nil && strings.HasPrefix(err.Error(), \"offset must be non-negative\") {\n    // clamp to 0 and retry\n}","preventionTips":["Clamp line-number arithmetic with Math.max(0, n)","Use origin \"end\" for tail reads instead of negative offsets","Validate integers before serializing to JSON"],"tags":["input-validation","numeric-range","tooling"],"backgroundTag":"invalid-argument-value","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}