wavetermdev/waveterm · error
size must be non-negative and less than MaxInt
Error message
size must be non-negative and less than MaxInt
What it means
ReadAt validates the requested size up front: it must be >= 0 and fit in an int. Sizes beyond math.MaxInt or negative sizes cannot be satisfied as a returned byte slice and would break downstream slice allocation, so the call fails immediately.
Source
Thrown at pkg/filestore/blockstore.go:372
if numCmds > IJsonHighCommands || incRatio >= IJsonHighRatio || (numCmds > IJsonLowCommands && incRatio >= IJsonLowRatio) {
err := s.compactIJson(ctx, entry)
if err != nil {
return err
}
}
return nil
})
}
func (s *FileStore) GetAllZoneIds(ctx context.Context) ([]string, error) {
return dbGetAllZoneIds(ctx)
}
// returns (offset, data, error)
// we return the offset because the offset may have been adjusted if the size was too big (for circular files)
func (s *FileStore) ReadAt(ctx context.Context, zoneId string, name string, offset int64, size int64) (rtnOffset int64, rtnData []byte, rtnErr error) {
if size < 0 || size > math.MaxInt {
return 0, nil, fmt.Errorf("size must be non-negative and less than MaxInt")
}
withLock(s, zoneId, name, func(entry *CacheEntry) error {
rtnOffset, rtnData, rtnErr = entry.readAt(ctx, offset, size, false)
return nil
})
return
}
// returns (offset, data, error)
func (s *FileStore) ReadFile(ctx context.Context, zoneId string, name string) (rtnOffset int64, rtnData []byte, rtnErr error) {
withLock(s, zoneId, name, func(entry *CacheEntry) error {
rtnOffset, rtnData, rtnErr = entry.readAt(ctx, 0, 0, true)
return nil
})
return
}
type FlushStats struct {View on GitHub (pinned to a4447c1563)
Solutions
- Clamp size to the actual file size before calling ReadAt (obtain it via ReadAt with a small size/stat or track it).
- Pass a bounded size (e.g. remaining bytes = file.Size - offset) instead of a sentinel.
- Read large files in chunks in a loop rather than one MaxInt-sized request.
Example fix
// before data, err := fs.ReadAt(ctx, zone, name, 0, -1) // meant 'read all' // after size := int64(1 << 20) rtnOffset, data, err := fs.ReadAt(ctx, zone, name, 0, size)
Defensive patterns
Strategy: validation
Validate before calling
if size < 0 || size > math.MaxInt { return fmt.Errorf("invalid read size %d", size) } Type guard
func validReadSize(size int64) bool { return size >= 0 && size <= math.MaxInt } Prevention
- Never pass -1 or math.MaxInt64 as a 'read everything' sentinel.
- Compute size from the real file size (file.Size - offset) and clamp.
- Read large files in bounded chunks.
When it happens
Trigger: Calling ReadAt(ctx, zoneId, name, offset, size) with size < 0 or size > math.MaxInt — e.g. passing -1 to mean 'read all', or computing size as an unbounded int64 sum of part sizes.
Common situations: Using -1 or math.MaxInt64 as a sentinel for 'read the whole file'; int overflow when casting buffer lengths; copying size values from APIs that use signed 64-bit sizes.
Related errors
- offset must be non-negative
- size must be greater than 0
- max size must be non-negative
- circular file must have a max size
- circular file cannot be ijson
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/f11b5ddfe428a3bc.
Report an issue: GitHub.