{"record":{"id":"d6e08ff37782574b","repo":"temporalio/temporal","slug":"w-state-namespace-failover-version-ref-namespa-d6e08f","errorCode":null,"errorMessage":"%w: state namespace failover version > ref namespace failover version: %v > %v","messagePattern":"%w: state namespace failover version > ref namespace failover version: (.+?) > (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/persistence/transitionhistory/transition_history.go","lineNumber":99,"sourceCode":"func StalenessCheck(\n\thistory []*persistencespb.VersionedTransition,\n\trefVersionedTransition *persistencespb.VersionedTransition,\n) error {\n\tif len(history) == 0 {\n\t\treturn serviceerror.NewInternal(\"state has empty transition history\")\n\t}\n\tidx, minTransitionCount, maxTransitionCount := transitionHistoryRangeForVersion(history, refVersionedTransition.NamespaceFailoverVersion)\n\tif idx == -1 {\n\t\tlastItem := history[len(history)-1]\n\t\tif lastItem.NamespaceFailoverVersion < refVersionedTransition.NamespaceFailoverVersion {\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"%w: state namespace failover version < ref namespace failover version: %v < %v\",\n\t\t\t\tconsts.ErrStaleState,\n\t\t\t\tlastItem.NamespaceFailoverVersion,\n\t\t\t\trefVersionedTransition.NamespaceFailoverVersion,\n\t\t\t)\n\t\t}\n\t\treturn fmt.Errorf(\n\t\t\t\"%w: state namespace failover version > ref namespace failover version: %v > %v\",\n\t\t\tconsts.ErrStaleReference,\n\t\t\tlastItem.NamespaceFailoverVersion,\n\t\t\trefVersionedTransition.NamespaceFailoverVersion,\n\t\t)\n\t}\n\tif idx == len(history)-1 && maxTransitionCount < refVersionedTransition.TransitionCount {\n\t\treturn fmt.Errorf(\n\t\t\t\"%w: state transition count < ref transition count: %v < %v\",\n\t\t\tconsts.ErrStaleState,\n\t\t\tmaxTransitionCount,\n\t\t\trefVersionedTransition.TransitionCount,\n\t\t)\n\t}\n\tif minTransitionCount > refVersionedTransition.TransitionCount || maxTransitionCount < refVersionedTransition.TransitionCount {\n\t\treturn fmt.Errorf(\n\t\t\t\"%w: ref transition count out of range for version %v: %v not in [%v, %v]\",\n\t\t\tconsts.ErrStaleReference,","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/persistence/transitionhistory/transition_history.go#L81-L117","documentation":"The mirror image of the stale-state case: when the reference transition's namespace failover version is OLDER than everything in the state's transition history, the state is actually newer than the reference, so StalenessCheck returns consts.ErrStaleReference wrapped with both versions. This tells callers that the incoming reference (event/replication task) is outdated and must not be applied to the current state.","triggerScenarios":"Calling StalenessCheck (via IsStale, applyBackfillEvents, ReplicateVersionedTransition, GetOrPollWorkflowMutableState) with refVersionedTransition.NamespaceFailoverVersion less than the last history item's version and idx == -1.","commonSituations":"Duplicate or out-of-order replication tasks delivering pre-failover events after the namespace already failed over; replaying an old replication task queue after failover; source cluster not aware the namespace failed over on the target.","solutions":["Drop/ignore the stale reference: replication logic treats ErrStaleReference as a signal to skip the event rather than apply it.","Ensure the source cluster has learned about the namespace failover (namespace replication is bidirectional); check namespace replication status.","Verify replication task ordering/dedup on the receiving cluster; drain old replication queues after failover.","If events should legitimately be applied, use backfill APIs (backfill history events) which account for versioning instead of raw replication."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"func isStaleReference(err error) bool {\n    return errors.Is(err, consts.ErrStaleReference)\n}","typeGuard":"func isStaleReferenceErr(err error) bool { return errors.Is(err, consts.ErrStaleReference) }","tryCatchPattern":"err := transitionhistory.ReplicateVersionedTransition(state, ref)\nif errors.Is(err, consts.ErrStaleReference) {\n    return nil // safe to skip an outdated replication task\n}\nif err != nil { return err }","preventionTips":["Drain/dedup replication queues after a namespace failover.","Ensure the source cluster learns about failovers (bidirectional namespace replication).","Treat ErrStaleReference as a benign skip signal, not an operator fault."],"tags":["go","replication","namespace-failover","versioning"],"backgroundTag":"stale-reference-failover-version","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}