henrygd/beszel · warning
%s returned negative bytes: %d
Error message
%s returned negative bytes: %d
What it means
ReadStringFileLimited reads up to maxSize bytes from the file at path and returns the trimmed contents. A negative read count violates the io.Reader contract (n < 0 should only accompany a non-nil error, which is already handled above), so the function defensively rejects it rather than returning corrupted string data.
Source
Thrown at agent/utils/utils.go:74
return strings.TrimSpace(string(b)), true
}
// ReadStringFileLimited reads a file into a string with a maximum size (in bytes) to avoid
// allocating large buffers and potential panics with pseudo-files when the size is misreported.
func ReadStringFileLimited(path string, maxSize int) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", err
}
defer f.Close()
buf := make([]byte, maxSize)
n, err := f.Read(buf)
if err != nil && err != io.EOF {
return "", err
}
if n < 0 {
return "", fmt.Errorf("%s returned negative bytes: %d", path, n)
}
return strings.TrimSpace(string(buf[:n])), nil
}
// FileExists reports whether the given path exists.
func FileExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
// ReadUintFile parses a decimal uint64 value from a file.
func ReadUintFile(path string) (uint64, bool) {
raw, ok := ReadStringFileOK(path)
if !ok {
return 0, false
}
parsed, err := strconv.ParseUint(raw, 10, 64)
if err != nil {View on GitHub (pinned to b38fb7dafa)
Solutions
- Close and reopen the file and retry the read; transient file-handle state is the most plausible cause.
- Check whether any custom io.Reader replaces os.File in this path and fix its Read to never return negative n.
- Report upstream if reproducible with a plain os.File — this indicates a runtime or filesystem driver bug.
- Log the raw (n, err) pair when this triggers to diagnose the offending reader.
Example fix
// before
n, err := f.Read(buf)
if n < 0 {
return "", fmt.Errorf("%s returned negative bytes: %d", path, n)
}
// after
n, err := io.ReadFull(io.LimitReader(f, int64(maxSize)), buf)
if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
return "", err
} // n is never negative by construction Defensive patterns
Strategy: validation
Validate before calling
// prefer bounded, contract-safe reads and stat before reading
if fi, err := os.Stat(path); err != nil || fi.Size() > int64(maxSize) {
return fmt.Errorf("file %s missing or too large", path)
} Type guard
func validReadCount(n int) bool { return n >= 0 && n <= maxSize } Try / catch
s, err := utils.ReadStringFileLimited(path, maxSize)
if err != nil {
if strings.Contains(err.Error(), "returned negative bytes") {
// retry once with a fresh handle or fall back to os.ReadFile
}
return err
} Prevention
- Never substitute custom readers with broken Read implementations for os.File.
- Use io.LimitReader/io.ReadFull for bounded reads.
- Stat the file before reading to sanity-check size.
- Report persistent occurrences as a runtime/filesystem bug.
When it happens
Trigger: f.Read(buf) returns n < 0 with a nil or EOF error — indicative of a misbehaving custom io.Reader or a corrupted file handle; os.File.Read never legitimately does this.
Common situations: Extremely rare; seen when a test/mock reader is substituted for os.File, under FUSE or exotic filesystem quirks, or while fuzzing. Indicates a reader implementation bug rather than a caller mistake.
Related errors
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/11cbdb88520545b1.
Report an issue: GitHub.