redis/go-redis · error

redis: can't parse reply=%T reading string

Error message

redis: can't parse reply=%T reading string

What it means

This helper converts a parsed RESP value into a *string and errors when the value's Go type is not string. It is used by vector-set attribute parsing (e.g. VGETATTR); a non-string reply (nil, integer, byte slice from a custom reader) cannot be assigned, so this error surfaces.

Source

Thrown at command.go:8753

		}
	}
	return &VectorScoreSliceSliceCmd{
		baseCmd: cmd.cloneBaseCmd(),
		val:     val,
	}
}

func readVectorAttribStringOrNil(rd *proto.Reader) (*string, error) {
	v, err := rd.ReadReply()
	if err != nil {
		if err == proto.Nil {
			return nil, nil
		}
		return nil, err
	}
	s, ok := v.(string)
	if !ok {
		return nil, fmt.Errorf("redis: can't parse reply=%T reading string", v)
	}
	return &s, nil
}

type VectorAttribSliceCmd struct {
	baseCmd

	val []VectorAttrib
}

var _ Cmder = (*VectorAttribSliceCmd)(nil)

func NewVectorAttribSliceCmd(ctx context.Context, args ...any) *VectorAttribSliceCmd {
	return &VectorAttribSliceCmd{
		baseCmd: baseCmd{
			ctx:  ctx,
			args: args,
		},

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Verify the attribute exists on the element (VGETATTR key element) before fetching it in Go.
  2. Check nil handling: if the attribute may be absent, treat the nil reply as 'not found' rather than a string.
  3. Upgrade go-redis to the latest version for improved null/type handling in vector commands.
  4. Inspect the raw reply with redis-cli to confirm the server returns a bulk string.

Example fix

// before: attribute missing -> nil reply -> type error
attr, err := rdb.VGetAttr(ctx, "pts", "elem", "color")
// redis: can't parse reply=<nil> reading string

// after: check existence first
emb, _ := rdb.VEmb(ctx, "pts", "elem", false)
if emb != nil {
    attr, err := rdb.VGetAttr(ctx, "pts", "elem", "color")
}
Defensive patterns

Strategy: type-guard

Validate before calling

exists, err := rdb.VEmb(ctx, "pts", "elem", false).Result()
if err != nil || exists == nil {
    // element missing; skip attribute fetch
}

Type guard

func asStringReply(v interface{}) (*string, bool) {
    s, ok := v.(string)
    if !ok { return nil, false }
    return &s, true
}

Try / catch

attr, err := rdb.VGetAttr(ctx, "pts", "elem", "color")
if err != nil {
    if strings.Contains(err.Error(), "can't parse reply") {
        // treat as missing/unsupported attribute
    }
    return err
}

Prevention

When it happens

Trigger: Calling VGetAttr() (or any path using this string reader at command.go:~8753) where the RESP reply decodes to a non-string type — e.g. a nil bulk string versus an actual value.

Common situations: Requesting an attribute that does not exist and the server replying with a null the client maps to non-string; RESP2/RESP3 encoding differences; custom dialer/reader wrappers altering types.

Related errors


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