redis/go-redis · error
errors.New(cmd.val) (dynamic: the server's shutdown reason r
Error message
errors.New(cmd.val) (dynamic: the server's shutdown reason reply is wrapped as the error)
What it means
When the SHUTDOWN command (Shutdown/ShutdownSync) gets a string reply instead of the connection closing, the server did not quit; the reply text is wrapped as the command's error via errors.New(cmd.val). The error message is dynamic — it is whatever reason the server replied with.
Source
Thrown at commands.go:767
}
func (c cmdable) shutdown(ctx context.Context, modifier string) *StatusCmd {
var args []interface{}
if modifier == "" {
args = []interface{}{"shutdown"}
} else {
args = []interface{}{"shutdown", modifier}
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
if err := cmd.Err(); err != nil {
if err == io.EOF {
// Server quit as expected.
cmd.err = nil
}
} else {
// Server did not quit. String reply contains the reason.
cmd.err = errors.New(cmd.val)
cmd.val = ""
}
return cmd
}
func (c cmdable) Shutdown(ctx context.Context) *StatusCmd {
return c.shutdown(ctx, "")
}
func (c cmdable) ShutdownSave(ctx context.Context) *StatusCmd {
return c.shutdown(ctx, "save")
}
func (c cmdable) ShutdownNoSave(ctx context.Context) *StatusCmd {
return c.shutdown(ctx, "nosave")
}
// SlaveOf sets a Redis server as a replica of another, or promotes it to being a master.View on GitHub (pinned to c5cad058c7)
Solutions
- Inspect the error message — it is the server's own reason.
- Retry with ShutdownNoSave(ctx) (SHUTDOWN NOSAVE) if a failing persistence save is blocking shutdown.
- Check server logs for the underlying persistence/replication failure.
- Verify the connection user is allowed to run SHUTDOWN.
Example fix
// before
err := rdb.Shutdown(ctx).Err() // opaque server reason
// after
if err := rdb.Shutdown(ctx).Err(); err != nil {
// fall back to skipping the save
err = rdb.ShutdownNoSave(ctx).Err()
} Defensive patterns
Strategy: try-catch
Try / catch
if err := rdb.Shutdown(ctx).Err(); err != nil {
// err message is the server's own reason string
log.Printf("server refused shutdown: %v", err)
if err2 := rdb.ShutdownNoSave(ctx).Err(); err2 != nil {
log.Fatalf("shutdown failed: %v", err2)
}
} Prevention
- Prefer ShutdownNoSave when a failing RDB save may block shutdown.
- Expect the connection to close on success — any string reply means refusal.
- Check server logs alongside the returned reason.
When it happens
Trigger: Calling rdb.Shutdown(ctx) or rdb.ShutdownSync(ctx) when the server refuses to shut down, e.g. a failing RDB save blocking SHUTDOWN without SAVE/NOSAVE, or a permission refusal; the string reply carries the reason.
Common situations: Scripting shutdown of instances where a BGSAVE child failed (Redis refuses SHUTDOWN with save pending unless SAVE/NOSAVE is given); connection user lacks SHUTDOWN privileges.
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/802df02dc45571af.
Report an issue: GitHub.