Fix Redis MISCONF RDB Snapshot Errors in Django
Fix the Redis MISCONF error that blocks writes from Django and Celery: find why background saves fail (disk full, permissions, memory overcommit), restore writes safely, and decide whether the instance needs persistence at all.
Problem statement
Every cache write, session save, and Celery delay() suddenly fails with:
redis.exceptions.ResponseError: MISCONF Redis is configured to save RDB snapshots,
but it's currently unable to persist to disk. Commands that may modify the data set
are disabled, because this instance is configured to report errors during writes
if RDB snapshotting fails (stop-writes-on-bgsave-error option).
Reads still work, so pages that only read the cache may load, while logins and checkouts fail. Redis forks a child to write its RDB snapshot; when that child fails, Redis refuses writes to protect you from believing data is persisted when it is not. The fix is to make the background save succeed again, not just to switch the safety check off.
- Read the Redis log for the line after
Background saving started: it states the real error. - Check disk space and the
dirRedis writes to:redis-cli CONFIG GET diranddf -h. - Check that the
redisuser owns that directory. - If the fork fails with "Cannot allocate memory", set
vm.overcommit_memory = 1. - Run
redis-cli BGSAVEand confirmrdb_last_bgsave_status:okinINFO persistence. - For a cache-only instance, disable RDB with
save ""instead of ignoring errors.
Step-by-step solution
1. Find the real error
redis-cli INFO persistence | grep -E "rdb_last_bgsave_status|rdb_changes_since_last_save|rdb_last_bgsave_time_sec"
sudo journalctl -u redis-server --since "-2h" | grep -iE "save|fork|error"
The log line names the cause, for example:
Failed opening the temp RDB file temp-1234.rdb (in server root dir /var/lib/redis) for saving: Permission deniedWrite error saving DB on disk: No space left on deviceCan't save in background: fork: Cannot allocate memory
2. Fix disk space and the target directory
redis-cli CONFIG GET dir
redis-cli CONFIG GET dbfilename
df -h /var/lib/redis
If the disk is full, free space first; see Fix a Django Server With a Full Disk. An RDB write needs roughly as much free space as the dataset, because it writes a temp file before renaming it.
A common surprise: someone ran CONFIG SET dir /tmp or the config points at a directory that was cleaned up. Set it back and persist the config:
redis-cli CONFIG SET dir /var/lib/redis
redis-cli CONFIG REWRITE
If dir points somewhere odd that you did not set, treat it as a possible compromise: an exposed Redis without a password is commonly abused by rewriting dir and dbfilename. Bind Redis to private interfaces and require a password.
3. Fix ownership and permissions
ls -ld /var/lib/redis
sudo chown redis:redis /var/lib/redis
sudo chmod 750 /var/lib/redis
In Docker, the volume mounted at /data must be writable by the user the Redis image runs as (UID 999 in the official image).
4. Allow the fork to succeed
Redis forks a copy-on-write child to write the snapshot. With the default heuristic overcommit, the kernel can refuse a fork of a large process even though little extra memory is used in practice. Redis's own startup warning recommends:
echo "vm.overcommit_memory = 1" | sudo tee /etc/sysctl.d/90-redis.conf
sudo sysctl --system
Also make sure Redis has a maxmemory setting that leaves room for the rest of the server, and disable transparent huge pages if Redis warns about them, since they make copy-on-write much more expensive.
5. Restore writes and verify
redis-cli BGSAVE
sleep 5
redis-cli INFO persistence | grep rdb_last_bgsave_status
Once a background save succeeds, Redis accepts writes again automatically. If you need writes back immediately while you fix the cause, you can temporarily run redis-cli CONFIG SET stop-writes-on-bgsave-error no, but set it back to yes afterwards, or you will lose data silently the next time saves fail.
6. Decide whether this Redis needs RDB
A pure cache can be rebuilt from the database, so persistence is overhead. A Celery broker or session store usually should persist.
# cache-only instance
save ""
appendonly no
Verification check: rdb_last_bgsave_status:ok, CONFIG GET stop-writes-on-bgsave-error returns yes, and a Django shell cache.set("probe", 1) succeeds.
Explanation
stop-writes-on-bgsave-error yes is a deliberate safety feature. If Redis kept accepting writes while every snapshot failed, a restart would lose everything since the last good snapshot without warning. By refusing writes, Redis turns a silent durability failure into a loud availability failure. That trade-off is right for data you care about and wrong for a disposable cache, which is why the cleaner fix for caches is to stop snapshotting rather than to ignore errors.
Edge cases / notes
- Managed Redis handles persistence itself; MISCONF there usually means the plan is out of memory or disk. Contact the provider or scale up.
- Docker containers without volumes write snapshots into the container layer, which can fill the host disk and is lost on recreate. Mount a volume at
/data. - Large datasets make each fork slower and more memory-hungry. Watch
rdb_last_bgsave_time_secandlatest_fork_usec. - Replicas also write RDB during full sync. A replica with a full disk breaks replication with similar errors.
Next steps
- Pick persistence settings per role with Configure Redis Persistence for Django and Celery.
- For memory errors rather than disk errors, see Fix Redis OOM Command Not Allowed in Django.
FAQ
Is it safe to set stop-writes-on-bgsave-error to no?
Only briefly while fixing the cause. Left off, a restart can lose data silently.
Why do reads still work?
MISCONF blocks commands that modify data. Reads are safe because nothing new needs persisting.
Does this affect Celery?
Yes. Queueing a task writes to Redis, so delay() fails until saves succeed again.
Do I need RDB for a cache?
No. Disable snapshots on cache-only instances.