wavetermdev/waveterm · error
offset must be non-negative
Error message
offset must be non-negative
What it means
FileStore.WriteAt rejects any negative offset before touching the file. Writes to a block-backed file must start at a non-negative byte offset since the offset is mapped onto fixed-size data parts in the DB. The check happens up front so no lock or cache load occurs for an obviously invalid call.
Source
Thrown at pkg/filestore/blockstore.go:242
return nil
})
}
func (s *FileStore) WriteFile(ctx context.Context, zoneId string, name string, data []byte) error {
return withLock(s, zoneId, name, func(entry *CacheEntry) error {
err := entry.loadFileIntoCache(ctx)
if err != nil {
return err
}
entry.writeAt(0, data, true)
// since WriteFile can *truncate* the file, we need to flush the file to the DB immediately
return entry.flushToDB(ctx, true)
})
}
func (s *FileStore) WriteAt(ctx context.Context, zoneId string, name string, offset int64, data []byte) error {
if offset < 0 {
return fmt.Errorf("offset must be non-negative")
}
return withLock(s, zoneId, name, func(entry *CacheEntry) error {
err := entry.loadFileIntoCache(ctx)
if err != nil {
return err
}
file := entry.File
if offset > file.Size {
return fmt.Errorf("offset is past the end of the file")
}
partMap := file.computePartMap(offset, int64(len(data)))
incompleteParts := incompletePartsFromMap(partMap)
err = entry.loadDataPartsIntoCache(ctx, incompleteParts)
if err != nil {
return err
}
entry.writeAt(offset, data, false)
return nilView on GitHub (pinned to a4447c1563)
Solutions
- Validate offset >= 0 in the caller before invoking WriteAt.
- Fix the offset arithmetic that produced the negative value (check subtraction order and underflow).
- If appending is intended, compute offset from the current file size via a stat/ReadAt of size 0 instead of a sentinel.
Example fix
// before
fs.WriteAt(ctx, zone, name, -1, data) // meant 'append'
// after
var offset int64 = 0 // or track the known file size
if offset < 0 { return fmt.Errorf("invalid offset %d", offset) }
fs.WriteAt(ctx, zone, name, offset, data) Defensive patterns
Strategy: validation
Validate before calling
if offset < 0 { return fmt.Errorf("WriteAt: offset %d must be >= 0", offset) } Type guard
func validOffset(offset int64) bool { return offset >= 0 } Prevention
- Never use negative int64 values as sentinels for offsets.
- Check subtraction-based offset math for underflow.
- Centralize file writes behind a wrapper that validates offset first.
When it happens
Trigger: Calling WriteAt(ctx, zoneId, name, offset, data) with offset < 0, typically because an offset was computed from a subtraction (e.g. size - remaining) that underflowed, or a caller passed -1 as an 'unset' sentinel.
Common situations: Arithmetic on int64 offsets overflowing/underflowing, sentinel values like -1 used for 'append' mistakenly, or deserializing offsets from JSON/binary where a missing field defaults to a negative value.
Related errors
- size must be non-negative and less than MaxInt
- 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/9560f6ae28d00e14.
Report an issue: GitHub.