temporalio/temporal · critical

Version increment <= 0 or > 2147483647

Error message

Version increment <= 0 or > 2147483647

What it means

NewMetadata panics when failoverVersionIncrement is 0 or greater than math.MaxInt32 (2147483647). The failover version increment is used as a modulus/spacing factor to allocate non-overlapping failover version ranges per cluster, so it must be a positive 32-bit integer. Passing an invalid increment makes version arithmetic (GetNextFailoverVersion, ClusterNameForFailoverVersion) incorrect, hence the fail-fast panic.

Source

Thrown at common/cluster/metadata.go:152

func NewMetadata(
	enableGlobalNamespace bool,
	failoverVersionIncrement int64,
	masterClusterName string,
	currentClusterName string,
	clusterInfo map[string]ClusterInformation,
	clusterMetadataStore persistence.ClusterMetadataManager,
	refreshDuration dynamicconfig.DurationPropertyFn,
	logger log.Logger,
) Metadata {
	if len(clusterInfo) == 0 {
		panic("Empty cluster information")
	} else if len(masterClusterName) == 0 {
		panic("Master cluster name is empty")
	} else if len(currentClusterName) == 0 {
		panic("Current cluster name is empty")
	} else if failoverVersionIncrement == 0 || failoverVersionIncrement > math.MaxInt32 {
		panic("Version increment <= 0 or > 2147483647")
	}

	versionToClusterName, err := updateVersionToClusterName(clusterInfo, failoverVersionIncrement)
	if err != nil {
		// nolint:forbidigo // matches the other startup-config panics in this constructor
		panic(err.Error())
	}
	if _, ok := clusterInfo[currentClusterName]; !ok {
		panic("Current cluster is not specified in cluster info")
	}
	if _, ok := clusterInfo[masterClusterName]; !ok {
		panic("Master cluster is not specified in cluster info")
	}

	copyClusterInfo := make(map[string]ClusterInformation)
	maps.Copy(copyClusterInfo, clusterInfo)
	if refreshDuration == nil {
		refreshDuration = dynamicconfig.GetDurationPropertyFn(refreshInterval)

View on GitHub (pinned to bde624efd1)

Solutions

  1. Pass a valid positive increment (conventionally 1 for single cluster, or distinct small positive values per cluster setup), e.g. cluster.NewMetadata(clusterInfo, "master", "current", 1, nil, nil)
  2. Validate the config value in Go with an int32 cast before constructing metadata
  3. Use NewMetadataFromConfig so the increment is read from validated config defaults

Example fix

// before
md := cluster.NewMetadata(clusterInfo, "master", "current", 0, nil, nil)
// after
md := cluster.NewMetadata(clusterInfo, "master", "current", 1, nil, nil)
Defensive patterns

Strategy: validation

Validate before calling

if failoverVersionIncrement <= 0 || failoverVersionIncrement > math.MaxInt32 {
  return fmt.Errorf("failoverVersionIncrement must be in (0, %d], got %d", math.MaxInt32, failoverVersionIncrement)
}

Prevention

When it happens

Trigger: cluster.NewMetadata(..., failoverVersionIncrement=0, ...) or an increment larger than math.MaxInt32; typically a zero-valued struct or misread int64 config field passed directly.

Common situations: Config where failoverVersionIncrement was never set (defaults to 0), copying sample multi-cluster configs and changing the increment to a value like 4294967296, or tests constructing metadata manually with an unset parameter.

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 temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/93aad8ea93f3c1b0. Report an issue: GitHub.