gofr-dev/gofr · error

invalid offset: must be >= 0

Error message

invalid offset: must be >= 0

What it means

errInvalidOffset is returned by NewRangeReader when the requested byte offset is negative. Range reads start from a non-negative position in the remote file; a negative offset is nonsensical and rejected before any network call.

Source

Thrown at pkg/gofr/datasource/file/ftp/storage_adapter.go:22

	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"path"
	"strings"
	"time"

	"github.com/jlaffaye/ftp"
	"gofr.dev/pkg/gofr/datasource/file"
)

var (
	// Storage adapter errors.
	errFTPConfigNil            = errors.New("FTP config is nil")
	errFTPClientNotInitialized = errors.New("FTP client is not initialized")
	errEmptyObjectName         = errors.New("object name is empty")
	errInvalidOffset           = errors.New("invalid offset: must be >= 0")
	errEmptySourceOrDest       = errors.New("source and destination names cannot be empty")
	errSameSourceAndDest       = errors.New("source and destination are the same")
	errFailedToCreateReader    = errors.New("failed to create reader")
	errFailedToCreateWriter    = errors.New("failed to create writer")
	errObjectNotFound          = errors.New("object not found")
	errFailedToGetObjectAttrs  = errors.New("failed to get object attrs")
	errFailedToDeleteObject    = errors.New("failed to delete object")
	errFailedToListObjects     = errors.New("failed to list objects")
	errFailedToListDirectory   = errors.New("failed to list directory")
	errWriterAlreadyClosed     = errors.New("writer already closed")
	errFTPConfigInvalid        = errors.New("invalid FTP configuration: host and port are required")
)

// Config represents the FTP configuration.
type Config struct {
	Host        string        // FTP server hostname
	User        string        // FTP username
	Password    string        // FTP password

View on GitHub (pinned to 187eb24962)

Solutions

  1. Clamp offset to >= 0 before calling: if offset < 0 { offset = 0 }.
  2. Fix the arithmetic producing the negative value (guard subtraction by the actual size).
  3. Sanitize user-supplied resume positions at the API boundary.

Example fix

// before
offset := size - chunkSize // can be negative
r, err := adapter.NewRangeReader(ctx, name, offset, chunkSize)
// after
offset := size - chunkSize
if offset < 0 { offset = 0 }
r, err := adapter.NewRangeReader(ctx, name, offset, chunkSize)
Defensive patterns

Strategy: validation

Validate before calling

if offset < 0 { offset = 0 } // or reject: return fmt.Errorf("offset must be >= 0")

Type guard

func validOffset(offset, length int64) bool { return offset >= 0 && length > 0 }

Try / catch

if !validOffset(offset, length) {
    return fmt.Errorf("invalid range request: offset=%d", offset)
}
r, err := adapter.NewRangeReader(ctx, name, offset, length)

Prevention

When it happens

Trigger: Calling NewRangeReader(ctx, name, offset, length) with offset < 0 — e.g. computing offset as size-n when n > size, or passing an uninitialized int64 defaulting negative.

Common situations: Cursor/pagination arithmetic underflowing below zero; users supplying a resume position from untrusted input without clamping.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/6e7f6cdb93af10f5. Report an issue: GitHub.