Skip to main content
Redis · lesson 1 of 14
Redis beginner Lesson 1 of 14

Redis in Five Commands: SET, GET, TYPE, and a WRONGTYPE Error

Run a real Redis server in Docker in one command, then hit the error every new user eventually hits: calling GET on a key that isn't a string.

By SkillByExample · Published

redis redis-cli docker getting-started

A Redis server is a single Docker command away — no account, no cloud, no installer.

Running a real Redis server

docker run -d --name redis-lesson -p 6379:6379 redis:8-alpine
docker exec redis-lesson redis-cli PING
PONG

-p 6379:6379 publishes Redis’s default port to the host; docker exec ... redis-cli runs the client that ships inside the same container, which is what every example in this track uses. Every lesson assumes this container is running.

Strings: the simplest type

docker exec redis-lesson redis-cli SET book:1 "Dune"
docker exec redis-lesson redis-cli GET book:1
docker exec redis-lesson redis-cli EXISTS book:1
docker exec redis-lesson redis-cli EXISTS book:999
OK
Dune
1
0

SET and GET are the whole interface for a string — EXISTS returns 1 or 0, not a boolean, because RESP (Redis’s wire protocol) has no boolean type; everything is an integer, a string, or an array.

Every key has a type — and Redis enforces it

docker exec redis-lesson redis-cli LPUSH mylist a b c
docker exec redis-lesson redis-cli TYPE mylist
3
list

LPUSH created mylist as a list, not a string — TYPE confirms it. 3 is the list’s length after the push, not an error code; LPUSH returns the new length on success.

The bug: calling the wrong command for the type

docker exec redis-lesson redis-cli GET mylist
WRONGTYPE Operation against a key holding the wrong kind of value

mylist is real and populated — TYPE just confirmed it — but GET only understands strings. Redis doesn’t try to coerce a list into a string representation; it refuses outright, by design, rather than returning something a caller might silently misinterpret.

The fix: use the command for the actual type

docker exec redis-lesson redis-cli LRANGE mylist 0 -1
c
b
a

LRANGE is the list-reading command, and 0 -1 means “the whole list.” Notice the order: c, b, a — the reverse of how they were pushed. LPUSH inserts at the head of the list each time, so the last value pushed (c) ends up first.

Practice

1. Check multiple keys for existence in a single command.
docker exec redis-lesson redis-cli SET a 1
docker exec redis-lesson redis-cli SET b 2
docker exec redis-lesson redis-cli EXISTS a b nonexistent
OK
OK
2

EXISTS accepts multiple key names and returns the count of how many exist — not one result per key. Two out of three here, so 2.

2. Delete a key that doesn't exist and see what comes back.
docker exec redis-lesson redis-cli DEL nonexistent
0

DEL doesn’t error on a missing key — it returns the count of keys actually deleted, which is 0 when there was nothing to delete. Deleting is idempotent by design.

3. List every key currently in the database with KEYS, then clear it with FLUSHALL.
docker exec redis-lesson redis-cli KEYS "*"
docker exec redis-lesson redis-cli FLUSHALL
a
b
mylist
book:1
OK

KEYS "*" is fine here — a handful of keys in a learning container — but reads the entire keyspace in one blocking pass, which is exactly why it’s unsafe on a production-sized database. FLUSHALL wipes everything, useful for resetting between experiments.

Next: strings in depth — expiry, atomic counters, and the increment-on-a-non-number error.

Frequently Asked Questions

Is Redis just a cache?
Caching is Redis's most common use, but the name stands for REmote DIctionary Server, and it's more accurately a data structure server — strings, hashes, lists, sets, sorted sets, and streams are all first-class, with commands operating on their actual structure rather than treating everything as an opaque blob. This track uses it as exactly that: a server with typed data structures, not just a fast key-value cache.
Why did GET fail on a key that clearly existed?
TYPE mylist reported it as a list, and GET only works on strings — Redis enforces per-key types strictly, so calling the wrong command on a key raises WRONGTYPE rather than silently coercing or returning something misleading. Every data type has its own read commands (LRANGE for lists, HGETALL for hashes, and so on).
What does redis-cli actually connect to when run through docker exec?
docker exec redis-lesson redis-cli runs the redis-cli binary that ships inside the container, connecting to the Redis server also running in that same container over localhost — no network configuration needed. A client running outside the container would instead connect to 127.0.0.1:6379 on the host, since -p 6379:6379 published that port.
Why is KEYS * considered dangerous on a real server?
KEYS scans the entire keyspace in one blocking operation — fine on a toy dataset like this lesson's, but on a production database with millions of keys it can block every other client for seconds. SCAN exists specifically to do the same job incrementally, in small non-blocking batches, and is what production code should use instead.
Does data survive if the container restarts?
Not by default with this setup — redis:8-alpine with no volume mounted keeps data only in the container's memory and default ephemeral storage, which is intentional for a learning environment where a clean slate per lesson is a feature. The persistence lesson later in this track covers RDB and AOF, which are what make data survive a real restart.