wavetermdev/waveterm · error
ReadTailLines readLimit must be positive, got %d
Error message
ReadTailLines readLimit must be positive, got %d
What it means
ReadTailLines reads backwards from the end of a file in doubling windows up to readLimit bytes; a non-positive readLimit makes the window-growing algorithm meaningless, so it validates upfront and returns this error. It is an argument-contract error, not an I/O failure.
Source
Thrown at pkg/util/readutil/readutil.go:149
return nil, false, err
}
lines, _, err := ReadLines(rs, linesToRead, 0, 0)
if err != nil {
return nil, false, err
}
return lines, hasMore, nil
}
// ReadTailLines reads the last lineCount lines from a file, excluding the last lineOffset lines.
// It progressively reads larger windows from the end of the file (starting at 1MB, doubling up to readLimit)
// until it finds enough lines or reaches the limit. Returns the lines, stop reason, and any error.
// Stop reason is StopReasonBOF when beginning of file is reached, StopReasonReadLimit when byte limit is reached,
// or empty string for natural completion (found requested line count).
func ReadTailLines(file *os.File, lineCount int, lineOffset int, readLimit int64) ([]string, string, error) {
if readLimit <= 0 {
return nil, "", fmt.Errorf("ReadTailLines readLimit must be positive, got %d", readLimit)
}
fileInfo, err := file.Stat()
if err != nil {
return nil, "", err
}
fileSize := fileInfo.Size()
readBytes := int64(1024 * 1024)
if readLimit < readBytes {
readBytes = readLimit
}
for {
startPos := fileSize - readBytes
if startPos < 0 {
startPos = 0
readBytes = fileSizeView on GitHub (pinned to a4447c1563)
Solutions
- Pass a positive readLimit (e.g. 1MB default: 1<<20) at the call site
- Apply a default when config yields 0: if limit <= 0 { limit = defaultLimit }
- Check for arithmetic that can floor to zero before calling
- Validate the limit during config load so bad values fail early
Example fix
// before
lines, stop, err := readutil.ReadTailLines(f, 100, 0, cfg.MaxTailBytes) // may be 0
// after
limit := cfg.MaxTailBytes
if limit <= 0 {
limit = 1 << 20 // 1 MiB default
}
lines, stop, err := readutil.ReadTailLines(f, 100, 0, limit) Defensive patterns
Strategy: validation
Validate before calling
if readLimit <= 0 {
readLimit = 1 << 20 // default 1 MiB
}
lines, stop, err := readutil.ReadTailLines(f, lineCount, lineOffset, readLimit) Try / catch
lines, stop, err := readutil.ReadTailLines(f, n, off, limit)
if err != nil {
if strings.Contains(err.Error(), "readLimit must be positive") {
return fmt.Errorf("caller bug: invalid readLimit %d", limit)
}
return err
} Prevention
- Clamp limits from config to a positive minimum at load time
- Beware zero-value int64 fields passed as limits
- Watch for division/flooring arithmetic that can yield 0
- Document that readLimit is in bytes and must be > 0
When it happens
Trigger: Calling ReadTailLines(file, lineCount, lineOffset, 0) or with a negative readLimit — typically a zero-value int64 variable, a config that computed the limit incorrectly, or an uninitialized struct field passed as readLimit.
Common situations: Config parsing producing 0 for unset byte limits; integer division truncating a limit to 0; copying example code and omitting the limit argument; defaults not applied before the call.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- no window found with workspace ${data.workspaceid}
- missing zone file info for ${zoneId}:${fileName}
- Image too large (>5MB)
- Unsupported or invalid image type: ${blob.type}
- Invalid CSS color: ${String(color)}
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/5d6faf0054687b7d.
Report an issue: GitHub.