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
- Raise PoolSize so marked connections don't starve the usable set.
- Ensure the handoff worker pool (MaxWorkers) drains marked connections promptly — increase it under heavy migration load.
- Treat this sentinel in any custom pool/errgroup wrapper as 'try another connection', not a fatal error.
- 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
- Size PoolSize and MaxWorkers for concurrent handoff volume.
- Treat the sentinel as flow control, not an error, in wrappers.
- Keep HandoffQueueSize large so marked connections are relocated fast.
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
- connection marked for handoff
- redis: connection not available
- redis: connection not available for write operation
- redis: timed out trying to mark connection as unusable
- MaxWorkers must be greater than or equal to 0
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/153dda5e603cee03.json.
Report an issue: GitHub.