go-redis/redis · error

%w: cannot transition from %s to %s (valid from: %v)

Error message

%w: cannot transition from %s to %s (valid from: %v)

What it means

Error "%w: cannot transition from %s to %s (valid from: %v)" thrown in go-redis/redis.

Source

Thrown at internal/pool/conn_state.go:192

	for _, fromState := range validFromStates {
		// Try to atomically swap from fromState to targetState
		// If successful, we won the race and can proceed
		if sm.state.CompareAndSwap(uint32(fromState), uint32(targetState)) {
			// Success! We transitioned atomically
			// Hot path optimization: only check for waiters if transition succeeded
			// This avoids atomic load on every Get/Put when no waiters exist
			if sm.waiterCount.Load() > 0 {
				sm.notifyWaiters()
			}
			return targetState, nil
		}
	}

	// All CAS attempts failed - state is not valid for this transition
	// Return the current state so caller can decide what to do
	// Note: This error path allocates, but it's the exceptional case
	currentState := sm.GetState()
	return currentState, fmt.Errorf("%w: cannot transition from %s to %s (valid from: %v)",
		ErrInvalidStateTransition, currentState, targetState, validFromStates)
}

// Transition unconditionally transitions to the target state.
// Use with caution - prefer AwaitAndTransition or TryTransition for safety.
// This is useful for error paths or when you know the transition is valid.
func (sm *ConnStateMachine) Transition(targetState ConnState) {
	sm.state.Store(uint32(targetState))
	sm.notifyWaiters()
}

// AwaitAndTransition waits for the connection to reach one of the valid states,
// then atomically transitions to the target state.
// Returns the current state after the transition attempt and an error if the operation failed.
// The returned state is the CURRENT state (after the attempt), not the previous state.
// Returns error if timeout expires or context is cancelled.
//
// This method implements FIFO fairness - the first caller to wait gets priority

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Drive the connection through valid state transitions only (see the valid-from list in the error)
  2. Reset or replace the connection when it reaches an unexpected state

When it happens

Trigger: Thrown at internal/pool/conn_state.go:192 when the library encounters an invalid state.

Common situations: Centralize conn state changes in the state machine API rather than setting state ad hoc.


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/9541bee0ba2d63bd.json. Report an issue: GitHub.