Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Redis By James Joyner IV · · 8 min read

Redis Error Guide: 'WRONGTYPE Operation against a key holding the wrong kind of value'

Fix WRONGTYPE errors in Redis: diagnose key-type mismatches, colliding key names, wrong command for a type, and format drift using TYPE and SCAN.

  • #redis
  • #troubleshooting
  • #errors
  • #data-types

Overview

WRONGTYPE Operation against a key holding the wrong kind of value is returned when you run a command against a key whose data type does not match the command. Redis keys are strongly typed: a key is a string, list, set, sorted set, hash, or stream, and each command family only works on its own type. Running LPUSH on a key that holds a string, or GET on a key that holds a hash, raises WRONGTYPE.

The literal error:

(error) WRONGTYPE Operation against a key holding the wrong kind of value

This is almost always an application bug, not a Redis fault: two code paths use the same key name for different types, a key was created by an older serialization format, or a command was simply issued against the wrong key. It is deterministic — the same key + command always fails until the key’s type or name changes.

Symptoms

  • A specific command fails with WRONGTYPE for certain keys but not others.
  • Errors cluster around a shared key namespace (e.g. session:*, cache:*).
  • A new deploy that changed a value’s structure (string → hash) triggers failures for keys written by the old code.
  • TYPE <key> returns a different type than the command expects.
redis-cli TYPE session:42
string
redis-cli HGETALL session:42
(error) WRONGTYPE Operation against a key holding the wrong kind of value

Common Root Causes

1. Key name collision across types

Two features use the same key. One writes a string, another expects a hash.

redis-cli TYPE user:1000
redis-cli OBJECT ENCODING user:1000
string
embstr

If one code path does SET user:1000 ... and another does HSET user:1000 ..., the second fails.

2. Wrong command for the type

Using GET/SET on a hash, SADD on a list, INCR on a non-integer string, etc.

(error) WRONGTYPE Operation against a key holding the wrong kind of value

3. Serialization/format drift after a deploy

Code that previously stored a JSON string now stores a hash (or vice versa). Keys written before the deploy keep the old type and break the new reader.

4. Key TTL/eviction masking the bug

A short TTL can hide a collision (the wrong-type key expires between failures), making WRONGTYPE appear intermittent when it is actually deterministic per key.

Diagnostic Workflow

Step 1: Identify the exact key and its actual type

Capture the failing key from the app log, then:

redis-cli TYPE <key>
redis-cli OBJECT ENCODING <key>
redis-cli TTL <key>

TYPE tells you what the key really is; compare against what the command expects.

Step 2: Find how the key was created (colliding writers)

Search the codebase for the key pattern to find every command that touches it:

# in your app repo
grep -rnE "['\"](session|user|cache):" src/ | grep -iE 'set|hset|lpush|sadd|zadd'

Look for two different type families writing the same prefix.

Step 3: Scan for keys of the unexpected type in the namespace

# Never use KEYS in production; SCAN is non-blocking
redis-cli --scan --pattern 'session:*' | while read k; do
  printf '%s %s\n' "$(redis-cli TYPE "$k")" "$k"
done | sort | uniq -c | sort -rn | head
   9124 hash session:...
     37 string session:...

A minority type in a namespace pinpoints the offending writer.

Step 4: Inspect recent commands live

# WARNING: MONITOR is expensive; use briefly on a replica or low-traffic node
redis-cli MONITOR | grep -iE 'session:42'

You will see the command that wrote the wrong type.

Example Root Cause Analysis

After deploying a new session store, the app began throwing WRONGTYPE on HGETALL session:<id> for a fraction of users. TYPE session:42 returned string, not hash.

redis-cli --scan --pattern 'session:*' | while read k; do redis-cli TYPE "$k"; done \
  | sort | uniq -c
   9124 hash
     37 string

The old code path stored sessions as a serialized JSON string (SET session:<id> <json>); the new code reads them as a hash (HGETALL). Sessions written by the old build before the deploy remained strings and broke the new reader.

Fixes: (1) add a migration that converts or expires the legacy string sessions, and (2) make the reader defensive — check TYPE (or catch WRONGTYPE) and fall back to re-creating the session. As a stopgap, the legacy keys were expired:

redis-cli --scan --pattern 'session:*' | while read k; do
  [ "$(redis-cli TYPE "$k")" = string ] && redis-cli DEL "$k"
done

New logins re-created sessions as hashes and the errors stopped.

Prevention Best Practices

  • Namespace keys per type and per feature so two writers can never collide (e.g. session:hash:<id>).
  • Treat a data-format change (string ↔ hash) as a migration: version the key prefix or run a backfill.
  • Make readers defensive: check TYPE or catch WRONGTYPE and handle gracefully rather than crashing.
  • Add integration tests that write and read each key through its real code path.
  • Use --scan (never KEYS) to audit key types in a namespace during incidents.
  • Browse more Redis error guides for related data-model pitfalls.

Quick Command Reference

# What type is this key really?
redis-cli TYPE <key>
redis-cli OBJECT ENCODING <key>
redis-cli TTL <key>

# Audit a namespace for mixed types (non-blocking)
redis-cli --scan --pattern 'session:*' | while read k; do
  printf '%s %s\n' "$(redis-cli TYPE "$k")" "$k"; done | sort | uniq -c

# Watch the command that writes a key (use sparingly)
redis-cli MONITOR | grep 'session:42'

# Remove offending legacy keys
redis-cli --scan --pattern 'session:*' | while read k; do
  [ "$(redis-cli TYPE "$k")" = string ] && redis-cli DEL "$k"; done

Conclusion

WRONGTYPE Operation against a key holding the wrong kind of value means the command and the key’s stored type disagree. It is a deterministic application-level bug, not a broker failure. The usual causes:

  1. Two code paths use the same key name for different types (collision).
  2. The wrong command family was issued for the key’s type.
  3. A serialization/format change left old keys in the previous type.
  4. TTL/eviction masked the bug into looking intermittent.

TYPE and OBJECT ENCODING on the failing key, plus a --scan audit of the namespace, immediately reveal the mismatch. Fix it with per-type namespacing, defensive readers, and treating format changes as migrations.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.