Redis Error Guide: 'BUSYKEY Target key name already exists' — Use REPLACE on RESTORE, COPY, and MIGRATE
Fix BUSYKEY Target key name already exists in Redis: understand RESTORE, COPY, and MIGRATE overwrite behavior and add REPLACE to make migrations idempotent.
- #redis
- #database
- #troubleshooting
- #errors
Stuck on this Redis error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
Redis returns BUSYKEY when a command that creates a key at a specific name finds that the name is already occupied and you did not tell it to overwrite. It is raised by RESTORE (deserializing a DUMP payload), COPY (duplicating a key), and MIGRATE (moving keys to another instance) whenever the destination key already exists and no REPLACE option was given.
The literal error clients receive:
(error) BUSYKEY Target key name already exists
This is a safety default, not a failure: these commands refuse to clobber existing data unless you explicitly opt in with REPLACE. It most often appears when a migration or import is retried — the first run created the key, and the retry hits the key it just wrote.
Symptoms
RESTORE,COPY, orMIGRATEfails withBUSYKEYfor keys that already exist on the destination.- A migration or restore that is re-run (after a partial failure) fails on exactly the keys the first pass wrote.
- Manual
DUMP/RESTOREround-trips fail on the second attempt.
redis-cli RESTORE user:42 0 "$PAYLOAD"
(error) BUSYKEY Target key name already exists
redis-cli EXISTS user:42
(integer) 1
Common Root Causes
1. RESTORE onto an existing key without REPLACE
The destination already holds user:42, and RESTORE refuses to overwrite it.
redis-cli TYPE user:42
hash
2. A retried or resumed migration
A migration script partially succeeded, then re-ran from the start; every key the first pass created now trips BUSYKEY.
3. COPY to an occupied destination
redis-cli COPY cart:src cart:dst
(error) BUSYKEY Target key name already exists
4. MIGRATE where the key exists on the target
Moving a key that was already moved (or exists independently) on the destination instance.
redis-cli MIGRATE dst 6379 order:9 0 5000
(error) BUSYKEY Target key name already exists
Diagnostic Workflow
Step 1: Confirm the key already exists and its type
redis-cli EXISTS user:42
redis-cli TYPE user:42
redis-cli TTL user:42
If EXISTS returns 1, BUSYKEY is expected without REPLACE.
Step 2: Decide whether overwriting is safe
Compare the existing value with what you are about to write. On a migration retry it is usually the same data; for an import into a shared namespace it may not be.
redis-cli MEMORY USAGE user:42
redis-cli OBJECT ENCODING user:42
Step 3: For MIGRATE, check both ends
# Source
redis-cli -h SRC EXISTS order:9
# Destination
redis-cli -h DST EXISTS order:9
Step 4: Verify your DUMP payload matches the target version
A RESTORE from an incompatible or truncated DUMP can fail differently (DUMP payload version or checksum are wrong); BUSYKEY specifically means the payload is fine but the name is taken.
redis-cli -h SRC DUMP order:9 | wc -c # non-empty payload
Step 5: Read the migration logs
sudo journalctl -u redis-server --no-pager | grep -iE 'BUSYKEY|RESTORE|MIGRATE' | tail
Example Root Cause Analysis
A cross-datacenter migration script iterates keys with SCAN and moves each with DUMP/RESTORE. It crashes at 60% through a batch and is restarted from the beginning. Immediately it floods with BUSYKEY Target key name already exists on every key in the first 60%.
The cause is clear: the destination already holds the keys the first run wrote, and the RESTORE call was written without REPLACE, so re-running is not idempotent:
redis-cli -h DST EXISTS user:42 # (integer) 1 — written by the first pass
The fix is to make the migration idempotent by adding REPLACE, which overwrites the destination key with the fresh payload (and its TTL) instead of erroring:
TTL=$(redis-cli -h SRC PTTL user:42)
redis-cli -h SRC DUMP user:42 | \
redis-cli -h DST -x RESTORE user:42 "$TTL" REPLACE # OK — overwrites
Because REPLACE makes each step safe to repeat, the script can now be re-run end-to-end after any crash without hitting BUSYKEY. The team verified TYPE/TTL on the destination before deleting the source.
Prevention Best Practices
- Add
REPLACEtoRESTORE,COPY, andMIGRATEin any migration or import that must be safely re-runnable — idempotency is the goal. - Preserve TTLs explicitly: pass the source
PTTLtoRESTOREso overwritten keys keep their expiry. - Before overwriting in a shared namespace, confirm you are not clobbering a different owner’s data —
REPLACEis unconditional. - Checkpoint migration progress so a resume skips already-moved keys instead of relying on
BUSYKEYas flow control. - For cluster moves, remember
MIGRATE ... COPY REPLACEkeeps the source and overwrites the target — choose the flags deliberately. - Feed migration errors into the free incident assistant, and browse more Redis guides.
Quick Command Reference
# Confirm the destination key exists
redis-cli EXISTS user:42
redis-cli TYPE user:42
# Idempotent restore that preserves TTL and overwrites
TTL=$(redis-cli -h SRC PTTL user:42)
redis-cli -h SRC DUMP user:42 | redis-cli -h DST -x RESTORE user:42 "$TTL" REPLACE
# Overwrite-safe copy and migrate
redis-cli COPY cart:src cart:dst REPLACE
redis-cli MIGRATE dst 6379 order:9 0 5000 COPY REPLACE
Conclusion
BUSYKEY Target key name already exists means a RESTORE, COPY, or MIGRATE found the destination name occupied and refused to overwrite it. The typical root causes are:
RESTOREonto an existing key withoutREPLACE.- A retried or resumed migration re-writing keys the first pass created.
COPY/MIGRATEto a destination that already holds the key.
The fix is almost always to add REPLACE so the operation is idempotent — but only after confirming you are not clobbering data a different owner cares about, and remembering to carry the TTL across so overwritten keys keep their expiry.
Fixed it? Get 500 Redis & DevOps AI prompts — free
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.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
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.