juicedata/juicefs · error
invalid HSCAN response for %s: odd number of elements: %d
Error message
invalid HSCAN response for %s: odd number of elements: %d
What it means
hscanToMap scans a Redis hash via HSCAN and expects each batch to be flat key/value pairs. Redis guarantees an even number of elements; receiving an odd count means the response is malformed (protocol/proxy problem or a wrapped/incompatible reply), so the function refuses to build a partially-wrong map and returns this error.
Source
Thrown at pkg/meta/redis.go:3978
}
if len(keys) > 0 {
if err = f(keys); err != nil {
return err
}
}
if c == 0 {
break
}
cursor = c
}
return nil
}
func (m *redisMeta) hscanToMap(ctx context.Context, key string) (map[string]string, error) {
result := make(map[string]string)
err := m.hscan(ctx, key, func(keys []string) error {
if len(keys)%2 != 0 {
return fmt.Errorf("invalid HSCAN response for %s: odd number of elements: %d", key, len(keys))
}
for i := 0; i < len(keys); i += 2 {
result[keys[i]] = keys[i+1]
}
return nil
})
if err != nil {
return nil, err
}
return result, nil
}
func (m *redisMeta) CleanupSlices(ctx Context) syscall.Errno {
logger.Debugf("start cleanup...")
m.cleanupLeakedInodes(true)
m.cleanupLeakedChunks(true)
m.cleanupOldSliceRefs(true)
return m.baseMeta.CleanupSlices(ctx)View on GitHub (pinned to c9a67b23e8)
Solutions
- Identify the middleware/proxy between the client and Redis and test HSCAN against real Redis directly (redis-cli HSCAN key 0).
- Upgrade or bypass the non-conforming proxy/compatible server.
- Retry the scan; a transient truncated reply may succeed on retry.
- If reproducible, capture the reply (MONITOR or tcpdump) and report to the proxy/storage vendor.
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check the backend conforms
keys, err := doRawHscan(testKey)
if err != nil || len(keys)%2 != 0 { log.Fatal("HSCAN replies are non-conforming; check proxy/compatible server") } Try / catch
m, err := hscanToMap(ctx, key)
if err != nil && strings.Contains(err.Error(), "invalid HSCAN response") {
logger.Warnf("malformed HSCAN from %s, retrying once", key)
m, err = hscanToMap(ctx, key)
} Prevention
- Test Redis-compatible backends (KeyDB, proxies) for HSCAN conformance before production
- Avoid middleware that rewrites multi-bulk replies
- Pin to well-known-conformant Redis versions/proxies
When it happens
Trigger: HSCAN on a hash (used by cleanup/maintenance scans over delSlices/sliceRefs-style keys) returning a keys slice whose length is not even — typically from a broken proxy, custom Redis-compatible server, or corrupted reply handling.
Common situations: Using Redis-compatible stores (KeyDB, Dragonfly, older Twemproxy/Codis) with non-conforming HSCAN replies; custom network middleware mangling multi-bulk replies.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- database %s is used by volume %s
- load setting: %s
- new session: %s
- invalid redisVersion: %v
- load user/group quotas: %w
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/f004cf962072bec2.
Report an issue: GitHub.