go-redis/redis · info

connection marked for handoff with state

Error message

connection marked for handoff with state

What it means

Returned by PoolHook.OnGet (pool_hook.go:127) when a pooled connection has ShouldHandoff() == true — it received a MOVING notification and is awaiting relocation, so it must not be handed out for new commands. Like error 50 this is flow control: the pool skips it and selects another connection.

Source

Thrown at maintnotifications/errors.go:51

var (
	// ErrHandoffQueueFull is returned when the handoff queue is full
	ErrHandoffQueueFull = errors.New(logs.HandoffQueueFullError())
)

// Notification errors
var (
	// ErrInvalidNotification is returned when a notification is in an invalid format
	ErrInvalidNotification = errors.New(logs.InvalidNotificationError())
)

// connection handoff errors
var (
	// ErrConnectionMarkedForHandoff is returned when a connection is marked for handoff
	// and should not be used until the handoff is complete
	ErrConnectionMarkedForHandoff = errors.New(logs.ConnectionMarkedForHandoffErrorMessage)
	// ErrConnectionMarkedForHandoffWithState is returned when a connection is marked for handoff
	// and should not be used until the handoff is complete
	ErrConnectionMarkedForHandoffWithState = errors.New(logs.ConnectionMarkedForHandoffErrorMessage + " with state")
	// ErrConnectionInvalidHandoffState is returned when a connection is in an invalid state for handoff
	ErrConnectionInvalidHandoffState = errors.New(logs.ConnectionInvalidHandoffStateErrorMessage)
)

// shutdown errors
var (
	// ErrShutdown is returned when the maintnotifications manager is shutdown
	ErrShutdown = errors.New(logs.ShutdownError())
)

// circuit breaker errors
var (
	// ErrCircuitBreakerOpen is returned when the circuit breaker is open
	ErrCircuitBreakerOpen = errors.New(logs.CircuitBreakerOpenErrorMessage)
)

// circuit breaker configuration errors
var (

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Raise PoolSize so marked connections don't starve the usable set.
  2. Ensure the handoff worker pool (MaxWorkers) drains marked connections promptly — increase it under heavy migration load.
  3. Treat this sentinel in any custom pool/errgroup wrapper as 'try another connection', not a fatal error.
  4. Verify HandoffQueueSize is large enough that marked connections are queued quickly rather than lingering.
Defensive patterns

Strategy: retry

Try / catch

// Pool internally retries with another connection. If exposed, retry:
if errors.Is(err, maintnotifications.ErrConnectionMarkedForHandoffWithState) {
    return retryCommand(ctx, cmd)
}

Prevention

When it happens

Trigger: A connection received a MOVING push notification (state set to moving/handoff-pending) but has not yet been queued/processed by a worker; OnGet sees ShouldHandoff() and returns (false, ErrConnectionMarkedForHandoffWithState) so the connection is reserved for handoff rather than reused.

Common situations: Normal during migrations — many connections may be marked simultaneously. Becomes visible as a hard error only if the pool is exhausted of unmarked connections (very small PoolSize relative to active handoffs).

Related errors


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