gofr-dev/gofr · error

%w (got: %d)

Error message

%w (got: %d)

What it means

NewRangeReader rejects a negative offset because FTP byte ranges must be non-negative. The library returns errInvalidOffset including the offending value via "(got: %d)". This is a pure caller-input validation error raised before any network I/O.

Source

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

	if err != nil {
		if isFTPNotFoundError(err) {
			return nil, fmt.Errorf("%w %q: %w", errObjectNotFound, name, err)
		}

		return nil, fmt.Errorf("%w for %q: %w", errFailedToCreateReader, name, err)
	}

	return reader, nil
}

// NewRangeReader creates a range reader for the given object.
func (s *storageAdapter) NewRangeReader(_ context.Context, name string, offset, length int64) (io.ReadCloser, error) {
	if name == "" {
		return nil, errEmptyObjectName
	}

	if offset < 0 {
		return nil, fmt.Errorf("%w (got: %d)", errInvalidOffset, offset)
	}

	if s.conn == nil {
		return nil, errFTPClientNotInitialized
	}

	objectPath := s.buildPath(name)

	reader, err := s.conn.RetrFrom(objectPath, uint64(offset))
	if err != nil {
		if isFTPNotFoundError(err) {
			return nil, fmt.Errorf("%w %q: %w", errObjectNotFound, name, err)
		}

		return nil, fmt.Errorf("%w for %q at offset %d: %w", errFailedToCreateReader, name, offset, err)
	}

	// FTP doesn't support length limit in RetrFrom, so wrap in LimitReader

View on GitHub (pinned to 187eb24962)

Solutions

  1. Clamp the offset to 0 before calling: if offset < 0 { offset = 0 }
  2. For tail reads, first StatObject to get the size and compute offset = size - n
  3. Check the caller's offset computation for underflow (e.g. size - n when n > size)

Example fix

// before
r, err := store.NewRangeReader(ctx, "log.txt", -1024, 1024)
// after
info, _ := store.StatObject(ctx, "log.txt")
offset := info.Size - 1024
if offset < 0 { offset = 0 }
r, err := store.NewRangeReader(ctx, "log.txt", offset, 1024)
Defensive patterns

Strategy: validation

Validate before calling

if offset < 0 {
    return errors.New("offset must be >= 0")
}
if length < 0 {
    length = 0 // read to EOF
}

Try / catch

r, err := store.NewRangeReader(ctx, name, offset, length)
if err != nil && strings.Contains(err.Error(), "invalid offset") {
    offset = 0
    r, err = store.NewRangeReader(ctx, name, offset, length)
}

Prevention

When it happens

Trigger: Calling storageAdapter.NewRangeReader(ctx, name, offset, length) with offset < 0 (e.g. -1 used as a sentinel for 'read from end' or an uninitialized int64).

Common situations: Passing -1 to mean 'tail of file' (not supported here), arithmetic underflow when computing offsets from sizes, uninitialized offset variables.

Related errors


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