redis/go-redis · error
redis: can't parse verbatim string reply: %q
Error message
redis: can't parse verbatim string reply: %q
What it means
This error is thrown when go-redis receives a RESP3 verbatim string reply (the '=' reply type, e.g. from LODEN/? commands like INFO with verbatim output) whose payload does not have the required 4-byte type prefix ('txt:' or 'mkd:') followed by the actual content. The protocol expects the first 3 characters to be a format identifier and the 4th character to be a colon. If the payload is shorter than 4 bytes or byte 3 is not ':', the reply is malformed for the verbatim-string contract and the library refuses to guess the format.
Source
Thrown at internal/proto/reader.go:421
return "", err
}
b := make([]byte, n+2)
_, err = io.ReadFull(r.rd, b)
if err != nil {
return "", err
}
return util.BytesToString(b[:n]), nil
}
func (r *Reader) readVerb(line []byte) (string, error) {
s, err := r.readStringReply(line)
if err != nil {
return "", err
}
if len(s) < 4 || s[3] != ':' {
return "", fmt.Errorf("redis: can't parse verbatim string reply: %q", line)
}
return s[4:], nil
}
func (r *Reader) readSlice(line []byte) ([]interface{}, error) {
n, err := replyLen(line)
if err != nil {
return nil, err
}
val := make([]interface{}, n)
for i := 0; i < len(val); i++ {
v, err := r.ReadReply()
if err != nil {
if err == Nil {
val[i] = nil
continue
}View on GitHub (pinned to c5cad058c7)
Solutions
- Check what command produced the reply; ensure the target actually supports that command and RESP3 verbatim strings (run with Protocol: 3 only against servers that support RESP3).
- Remove or bypass any RESP-rewriting proxy between the client and the Redis server, or upgrade it to a version that forwards '=' replies with the type prefix intact.
- If you control the server/module emitting the reply, make it prefix verbatim payloads with 'txt:' (or another valid 3-char format + ':').
- As a workaround, switch the connection to Protocol: 2 so the reply is delivered as a plain bulk string instead of a verbatim string, or parse the raw reply yourself via a custom hook.
Example fix
// before: forcing RESP3 against a proxy that mangles verbatim replies
opts := &redis.Options{Addr: "proxy:6379", Protocol: 3}
// after: use RESP2 so verbatim '=' replies arrive as plain bulk strings
opts := &redis.Options{Addr: "proxy:6379", Protocol: 2} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check: only issue verbatim-returning commands against servers confirmed to
// support RESP3 verbatim strings, and pin the protocol explicitly.
func verbatimSafe(opts *redis.Options) bool {
return opts.Protocol == 3 && !behindRewritingProxy(opts.Addr) // your own check
} Type guard
func isVerbatimParseError(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "redis: can't parse verbatim string reply:")
} Try / catch
res, err := client.Do(ctx, "DEBUG", "JMAP", key).Result()
if err != nil {
if isVerbatimParseError(err) {
// fallback: re-issue with RESP2 semantics or parse raw string yourself
res, err = fallbackPlainString(ctx, client, key)
}
if err != nil { return err }
} Prevention
- Run Protocol: 3 only against servers that fully implement RESP3 verbatim strings.
- Avoid putting reply-rewriting proxies (old Twemproxy/envoy configs) in front of verbatim-returning commands.
- Test module/debug commands against the exact server version and proxy chain used in production.
- Wrap raw Do() calls for exotic commands in a helper that maps parse errors to a domain error with the command name.
When it happens
Trigger: Calling any command that returns a RESP3 verbatim string ('=' reply) — such as DEBUG SLEEP, DEBUG JMAP, or module commands emitting verbatim strings — while the server returns a verbatim payload without the 'txt:'/'mkd:' prefix. Also triggered when a non-Redis or proxy server (e.g. a RESP proxy or a Twemproxy/envoy layer) replies with a bare bulk-like string using the '=' type instead of '$'. ReadReply() and ReadString() funnel through readVerb, so any of those surfaces the error.
Common situations: Talking to a RESP proxy or middleware that misformats verbatim replies; connecting to a Redis-compatible server (e.g. KeyDB fork quirks or an embedded/embedded-in-memory RESP implementation) that emits '=' replies without the type prefix; running with Protocol: 3 against a server that only partially implements RESP3; calling commands that shouldn't return verbatim strings against the wrong endpoint (e.g. sending an admin/debug command to a load balancer).
Related errors
- redis: RESP3 map key must be a scalar type, got %T
- bigInt(%s) value out of range
- redis: invalid map key %#v
- redis: can't parse int reply: %.100q
- redis: got %d elements in latency get, expected at least 4
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/7720a160b362236b.
Report an issue: GitHub.