apache/beam · error

end sequence number must be greater than 0

Error message

end sequence number must be greater than 0

What it means

errInvalidEndSeqNo is a sentinel error returned by the WithEndSeqNo NATS read option when the ending sequence number is zero or negative. Since NATS sequences are 1-based, an end bound must be at least 1 for the read range to be valid.

Source

Thrown at sdks/go/pkg/beam/io/natsio/read_option.go:23

// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package natsio

import "errors"

var (
	errInvalidFetchSize  = errors.New("fetch size must be greater than 0")
	errInvalidStartSeqNo = errors.New("start sequence number must be greater than 0")
	errInvalidEndSeqNo   = errors.New("end sequence number must be greater than 0")
)

type readOption struct {
	CredsFile  string
	TimePolicy timePolicy
	FetchSize  int
	StartSeqNo int64
	EndSeqNo   int64
}

// ReadOptionFn is a function that can be passed to Read to configure options for reading
// from NATS.
type ReadOptionFn func(option *readOption) error

// ReadUserCredentials sets the user credentials when connecting to NATS.
func ReadUserCredentials(credsFile string) ReadOptionFn {
	return func(o *readOption) error {
		o.CredsFile = credsFile

View on GitHub (pinned to 12126d8942)

Solutions

  1. Pass an end sequence >= 1, ensuring end >= start for a non-empty range.
  2. Validate range math before constructing options: if end <= 0, either omit the option (unbounded) or set the latest known sequence.
  3. Check the config source that supplies the end sequence for zero defaults.

Example fix

// before
opts = append(opts, natsio.WithEndSeqNo(end)) // end = 0 from missing config
// after
if end <= 0 {
    return fmt.Errorf("end sequence must be configured")
}
opts = append(opts, natsio.WithEndSeqNo(end))
Defensive patterns

Strategy: validation

Validate before calling

if endSeq <= 0 || endSeq < startSeq {
    return fmt.Errorf("endSeq must be >= 1 and >= startSeq (%d), got %d", startSeq, endSeq)
}
opts = append(opts, natsio.WithEndSeqNo(endSeq))

Try / catch

if err := applyReadOptions(opts...); err != nil {
    if errors.Is(err, errInvalidEndSeqNo) {
        return fmt.Errorf("end sequence must be >= 1: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Passing natsio.WithEndSeqNo(0) or a negative value into the read options, e.g. from an unset configuration value or a range computation that produced an empty/invalid upper bound.

Common situations: Reading a bounded range [start, end] where end was computed as start-1 or left at 0; missing flag/env for the end sequence; off-by-one when computing the last sequence to replay.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/9348ce8c8d62ef5f. Report an issue: GitHub.