nats-io/nats-server · error

bad sampling percentage, should be 1-100

Error message

bad sampling percentage, should be 1-100

What it means

ErrBadSampling is returned when the sampling percentage for service latency tracking is outside the valid range 1-100. The library enforces 1 >= sample <= 100; a value of 0 means sampling was triggered by a header and is allowed to bypass the check.

Source

Thrown at server/errors.go:120

	ErrAccountExists = errors.New("account exists")

	// ErrBadAccount represents a malformed or incorrect account.
	ErrBadAccount = errors.New("bad account")

	// ErrReservedAccount represents a reserved account that can not be created.
	ErrReservedAccount = errors.New("reserved account")

	// ErrMissingAccount is returned when an account does not exist.
	ErrMissingAccount = errors.New("account missing")

	// ErrMissingService is returned when an account does not have an exported service.
	ErrMissingService = errors.New("service missing")

	// ErrBadServiceType is returned when latency tracking is being applied to non-singleton response types.
	ErrBadServiceType = errors.New("bad service response type")

	// ErrBadSampling is returned when the sampling for latency tracking is not 1 >= sample <= 100.
	ErrBadSampling = errors.New("bad sampling percentage, should be 1-100")

	// ErrAccountValidation is returned when an account has failed validation.
	ErrAccountValidation = errors.New("account validation failed")

	// ErrAccountExpired is returned when an account has expired.
	ErrAccountExpired = errors.New("account expired")

	// ErrNoAccountResolver is returned when we attempt an update but do not have an account resolver.
	ErrNoAccountResolver = errors.New("account resolver missing")

	// ErrAccountResolverUpdateTooSoon is returned when we attempt an update too soon to last request.
	ErrAccountResolverUpdateTooSoon = errors.New("account resolver update too soon")

	// ErrAccountResolverSameClaims is returned when same claims have been fetched.
	ErrAccountResolverSameClaims = errors.New("account resolver no new claims")

	// ErrStreamImportAuthorization is returned when a stream import is not authorized.
	ErrStreamImportAuthorization = errors.New("stream import not authorized")

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Pass a sampling value between 1 and 100 inclusive (or 0 for header-triggered sampling)
  2. Clamp or validate any dynamically computed/user-supplied sampling percentage before the call
  3. Use a named constant for the default sampling (e.g. 100) instead of ad-hoc values
  4. If sampling should be disabled entirely, do not call the tracking API rather than passing 0/negative

Example fix

// before
acc.TrackServiceExportWithSampling("svc", "results", -1)
// after
sampling := 100
if sampling < 1 || sampling > 100 { sampling = 100 }
err := acc.TrackServiceExportWithSampling("svc", "results", sampling)
Defensive patterns

Strategy: validation

Validate before calling

func validSampling(s int) bool { return s == 0 || (s >= 1 && s <= 100) }
if !validSampling(sampling) { return fmt.Errorf("sampling must be 1-100 (or 0 for header-triggered), got %d", sampling) }

Type guard

null

Try / catch

if err := acc.TrackServiceExportWithSampling(svc, resp, sampling); err != nil {
	if errors.Is(err, ErrBadSampling) { sampling = 100 /* clamp and retry */ }
}

Prevention

When it happens

Trigger: Calling TrackServiceExportWithSampling with sampling < 1 or > 100, e.g. -1 (as in TestAccountRequestReplyTrackLatency at server/accounts_test.go:1738) or 101. Only sampling==0 (header-triggered) skips validation.

Common situations: Passing an uninitialized/negative int as sampling; confusing percentage with fraction (0.5 instead of 50); computing the percentage dynamically and producing out-of-range values; user-supplied config values not clamped before use.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/746c54115568db4d. Report an issue: GitHub.