redis/go-redis · error

redis: unexpected client info data (%s)

Error message

redis: unexpected client info data (%s)

What it means

CLIENT INFO returns a space-separated list of key=value pairs describing the connection. parseClientInfo splits each token on '=' and requires exactly two parts; any malformed token (extra '=', spaces inside values, null placeholder, or empty token) causes this error. The comment in the source notes fmt.Sscanf cannot handle null values, hence the hand-rolled parser.

Source

Thrown at command.go:7954

	if err != nil {
		return err
	}

	// sds o = catClientInfoString(sdsempty(), c);
	// o = sdscatlen(o,"\n",1);
	// addReplyVerbatim(c,o,sdslen(o),"txt");
	// sdsfree(o);
	cmd.val, err = parseClientInfo(strings.TrimSpace(txt))
	return err
}

// fmt.Sscanf() cannot handle null values
func parseClientInfo(txt string) (info *ClientInfo, err error) {
	info = &ClientInfo{}
	for _, s := range strings.Split(txt, " ") {
		kv := strings.Split(s, "=")
		if len(kv) != 2 {
			return nil, fmt.Errorf("redis: unexpected client info data (%s)", s)
		}
		key, val := kv[0], kv[1]

		switch key {
		case "id":
			info.ID, err = strconv.ParseInt(val, 10, 64)
		case "addr":
			info.Addr = val
		case "laddr":
			info.LAddr = val
		case "fd":
			info.FD, err = strconv.ParseInt(val, 10, 64)
		case "name":
			info.Name = val
		case "age":
			var age int
			if age, err = strconv.Atoi(val); err == nil {
				info.Age = time.Duration(age) * time.Second

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Set the connection name with characters free of spaces and '=' (CLIENT SETNAME / Options.ClientName).
  2. Print the raw CLIENT INFO (redis-cli CLIENT INFO) to find the offending token.
  3. Upgrade go-redis; newer parsers tolerate more edge cases in CLIENT INFO.
  4. If a proxy or module injects the bad field, fix or bypass it.

Example fix

// before: client name with spaces breaks parsing
rdb := redis.NewClient(&redis.Options{ClientName: "my app=v2"})
info, err := rdb.ClientInfo(ctx) // redis: unexpected client info data (app=v2)

// after: sanitize the name
rdb := redis.NewClient(&redis.Options{ClientName: "my-app-v2"})
info, err := rdb.ClientInfo(ctx)
Defensive patterns

Strategy: validation

Validate before calling

name := rdb.Options().ClientName
if strings.ContainsAny(name, " =") {
    // sanitize before connecting / calling CLIENT INFO
    name = strings.Map(func(r rune) rune {
        if r == ' ' || r == '=' { return '-' }
        return r
    }, name)
}

Try / catch

info, err := rdb.ClientInfo(ctx)
if err != nil {
    if strings.Contains(err.Error(), "unexpected client info data") {
        // fall back to raw CLIENT INFO string and parse defensively
    }
    return err
}

Prevention

When it happens

Trigger: Calling ClientInfo() (or echoing CLIENT INFO via conn) when the reply contains a token that is not a clean key=value pair — e.g. 'name=' with empty value, 'db=0 extra', or a null/empty segment.

Common situations: Connections with a client name containing spaces or '=' set via CLIENT SETNAME; proxies injecting attributes into CLIENT INFO; odd server builds emitting empty fields.

Related errors


AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01). Data as JSON: /api/errors/12c0452e20f9ade6. Report an issue: GitHub.