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
- 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)
- Validate the config value in Go with an int32 cast before constructing metadata
- 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
- Derive the increment from validated config rather than ad-hoc literals
- Keep per-cluster increments small and distinct (e.g. 1, 2, 3...)
- Add a startup self-check that constructs metadata and converts any panic into a fatal config error message
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
- <dynamic updateVersionToClusterName err>
- Current cluster name is empty
- Current cluster is not specified in cluster info
- Master cluster is not specified in cluster info
- ClusterMetadata encountered local namesapce with failover ve
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/93aad8ea93f3c1b0.
Report an issue: GitHub.