wavetermdev/waveterm · error
offset cannot be negative
Error message
offset cannot be negative
What it means
CacheEntry.readAt rejects negative offsets before loading the file. ReadAt is the main caller, but it can also be reached via compactIJson; the internal entry-level check catches offsets that the public wrapper did not pre-validate.
Source
Thrown at pkg/filestore/blockstore_cache.go:208
partIdx = partIdx % maxPart
}
partOffset := offset % partDataSize
partData := entry.getOrCreateDataCacheEntry(partIdx)
nw, newDce := partData.writeToPart(partOffset, data)
entry.DataEntries[partIdx] = newDce
data = data[nw:]
offset += nw
}
if endWriteOffset > entry.File.Size || replace {
entry.File.Size = endWriteOffset
}
entry.File.ModTs = time.Now().UnixMilli()
}
// returns (realOffset, data, error)
func (entry *CacheEntry) readAt(ctx context.Context, offset int64, size int64, readFull bool) (int64, []byte, error) {
if offset < 0 {
return 0, nil, fmt.Errorf("offset cannot be negative")
}
file, err := entry.loadFileForRead(ctx)
if err != nil {
return 0, nil, err
}
if readFull {
size = file.Size - offset
}
if offset+size > file.Size {
size = file.Size - offset
}
if file.Opts.Circular {
realDataOffset := int64(0)
if file.Size > file.Opts.MaxSize {
realDataOffset = file.Size - file.Opts.MaxSize
}
if offset < realDataOffset {
truncateAmt := realDataOffset - offsetView on GitHub (pinned to a4447c1563)
Solutions
- Validate offset >= 0 before calling ReadAt or any compaction entry point.
- If triggered from compactIJson, inspect the file's part map/size for corrupt metadata that yields negative offsets.
- Clamp computed offsets (e.g. max(0, computed)) where arithmetic can underflow.
Example fix
// before
fs.ReadAt(ctx, zone, name, userOffset, 1024) // userOffset unchecked
// after
if userOffset < 0 { return fmt.Errorf("invalid offset") }
fs.ReadAt(ctx, zone, name, userOffset, 1024) Defensive patterns
Strategy: validation
Validate before calling
if offset < 0 { return fmt.Errorf("ReadAt: offset %d must be >= 0", offset) } Type guard
func validOffset(offset int64) bool { return offset >= 0 } Prevention
- Validate offsets at API boundaries before they reach filestore calls.
- Clamp computed offsets (e.g. from compaction math) to >= 0.
- Never encode 'not set' as a negative offset.
When it happens
Trigger: Calling ReadAt with offset < 0, or compactIJson internally computing a negative offset from file state (e.g. a part offset calculation on a corrupt/oddly-sized file).
Common situations: Sentinel -1 offsets; offset arithmetic underflow in compaction; passing user-supplied offsets straight through without validation.
Related errors
- max size must be non-negative
- circular file must have a max size
- circular file cannot be ijson
- ijson budget requires ijson
- ijson budget must be non-negative
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/e67203cd7eb135cb.
Report an issue: GitHub.