Saltar al contenido principal
Redis

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

Cómo resolver el error WRONGTYPE en Redis. Ocurre cuando intentas usar un comando de un tipo de dato sobre una clave que almacena otro tipo diferente.

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

¿Por qué ocurre?

Redis es estrictamente tipado por clave. El error WRONGTYPE ocurre cuando: - Una clave existe como String pero intentas usar comandos de List, Set, Hash o ZSet sobre ella - La clave fue creada con un tipo y en otra parte del código se usa como otro tipo - Cambio de lógica: antes guardabas un String simple y ahora quieres guardar un Hash - En apps con múltiples servicios, dos servicios usan la misma clave con tipos distintos

Solución paso a paso

1. Verificar el tipo actual de la clave

# En redis-cli
TYPE mi:clave

# Respuestas posibles: string, list, set, hash, zset, stream

2. Eliminar la clave y recrearla con el tipo correcto

# Ver el valor actual
GET mi:clave        # si es string
HGETALL mi:clave    # si es hash
LRANGE mi:clave 0 -1 # si es list

# Eliminar y recrear DEL mi:clave HSET mi:clave campo1 "valor1" campo2 "valor2"

3. En Node.js con ioredis — manejar el error

import Redis from 'ioredis'
const redis = new Redis()

async function guardarUsuario(userId, userData) { const key = user:${userId}

try { // Verificar tipo antes de escribir const tipo = await redis.type(key) if (tipo !== 'none' && tipo !== 'hash') { await redis.del(key) console.warn(Clave ${key} tenía tipo incorrecto (${tipo}), eliminada) }

await redis.hset(key, userData) } catch (error) { if (error.message.includes('WRONGTYPE')) { await redis.del(key) await redis.hset(key, userData) } else { throw error } } }

4. Convención de naming para evitar colisiones de tipo

// Usar prefijos descriptivos del tipo
const KEYS = {
  userHash:    (id) => user:hash:${id},      // HSET/HGET
  sessionStr:  (id) => session:str:${id},    // SET/GET
  feedList:    (id) => feed:list:${id},      // LPUSH/LRANGE
  tagsSet:     (id) => tags:set:${id},       // SADD/SMEMBERS
  rankZset:    ()   => rank:zset:global,     // ZADD/ZRANGE
}

// Nunca mezclarás tipos en la misma clave await redis.hset(KEYS.userHash(userId), { name: 'Fran' }) await redis.set(KEYS.sessionStr(sessionId), token)

5. Migración: cambiar tipo de una clave con datos existentes

async function migrarStringAHash(redis, userId) {
  const key = user:${userId}
  const tipo = await redis.type(key)

if (tipo === 'string') { // Leer el valor antiguo const valorAntiguo = await redis.get(key) const ttl = await redis.ttl(key)

// Borrar y recrear como hash await redis.del(key) await redis.hset(key, { legacy_value: valorAntiguo })

// Mantener TTL original if (ttl > 0) await redis.expire(key, ttl) } }

Cómo evitarlo en el futuro

- Define los tipos de todas las claves Redis en un módulo central (`redis/keys.ts`) - Usa prefijos que incluyan el tipo: `user:hash:*`, `session:str:*` - Al cambiar la estructura de datos de una clave, incrementa el namespace: `user:v2:hash:*` - En tests, usa `FLUSHDB` al inicio para limpiar estado residual - Documenta el esquema de Redis igual que documentas el esquema de base de datos

Rediscachétipos de datosioredisnode-redis

¿Quieres que una IA te ayude? Genera el prompt perfecto para tu error:

Generador de Prompts

¿Necesitas desarrollo a medida?

Apps web, IA, módulos ERP — cuéntame tu proyecto.