Redis bir komutu çalıştıramadığında sonuç yerine bir hata mesajı döndürür ve bu mesaj her zaman büyük harfli bir ön ek ile başlar: ERR, WRONGTYPE, EXECABORT, NOSCRIPT, BUSY gibi. Ön ek hatanın türünü, ardından gelen açıklama ayrıntıyı söyler. En sık görülen komut hataları şunlardır: yanlış yazılmış ya da sunucuda olmayan komut (ERR unknown command), eksik ya da fazla argüman (ERR wrong number of arguments), yanlış seçenek (ERR syntax error), sayı beklenen yerde metin (ERR value is not an integer or out of range) ve anahtarın tipine uymayan komut (WRONGTYPE).
Bu yazıda Redis belgelerindeki "common errors" sayfalarından komut, transaction, betik ve stream hatalarını tek tek açıklıyor; her biri için belgedeki örneği ve çözüm yolunu veriyoruz. Bellek, kalıcılık, replikasyon ve protected mode hataları (OOM, MISCONF, READONLY, LOADING, DENIED) OOM, MISCONF ve READONLY hataları yazısında, cluster yönlendirmeleri (MOVED, ASK, CROSSSLOT) Redis Cluster ve hash slot yazısında, kimlik doğrulama hataları (NOAUTH, WRONGPASS, NOPERM) ise ACL kullanıcı ve yetki yönetimi yazısında. Serinin tamamı için Redis öğrenme rehberi.
Redis hataları nasıl görünür?

Redis sunucusundan gelen hata mesajları büyük harfli bir sözcükle başlar ve belgeler buna hata ön eki (error prefix) der. ERR genel amaçlı ön ektir; hata ERR ile başlıyorsa neyin yanlış gittiğini açıklama kısmı söyler. WRONGTYPE gibi özel ön ekler ise kodunuzun açıklamayı okumadan hata türünü ayırt edebilmesi için vardır. Belgelerin uyardığı bir istisna var: Redis Search, JSON ve pakete dahil diğer özelliklerin hataları bu kurala her zaman uymaz. Search hatalarının çoğu SEARCH_INDEX_NOT_FOUND gibi bir kodla başlar; bazı JSON, olasılıksal tip ve zaman serisi hatalarının ise hiç ön eki yoktur, örneğin Bad capacity. İstemci kütüphaneleri bu durumda mesajın ilk sözcüğünü ön ek sayar.
Hatayı nasıl gördüğünüz kullandığınız araca bağlıdır. redis-cli mesajın önüne (error) yazar. İstemci kütüphaneleri ise mesajı içeren bir istisna fırlatır ya da hata değeri döndürür. Bazı kütüphaneler yaygın ön ekleri kendi istisna sınıflarına çevirir ve ön eki mesajdan çıkarır; belgedeki örneğe göre redis-py, READONLY You can't write against a read only replica. hatasını ReadOnlyError: You can't write against a read only replica. olarak raporlar. Kütüphanelerin çoğu yalnızca birkaç ön ek için ayrı sınıf tanımlar ve geri kalan tüm hataları genel bir sunucu hatası sınıfıyla fırlatır; o durumda hataları mesajdaki ön eke bakarak ayırırsınız.
| Hata | Ne anlama gelir | İlk adım |
|---|---|---|
| ERR unknown command | Sunucu komut adını tanımıyor | Yazımı, sunucu sürümünü ve yüklü modülleri kontrol edin |
| ERR wrong number of arguments | Argüman sayısı yanlış | Komut sözdizimini ve boş listeleri kontrol edin |
| ERR syntax error | Seçenekler yanlış, yanlış yerde ya da birbiriyle çelişiyor | Seçenekleri komut sayfasıyla karşılaştırın |
| ERR value is not an integer or out of range | Tamsayı beklenen yerde başka bir değer var | Saklanan değeri ve argümanları kontrol edin |
| WRONGTYPE | Komut anahtarın veri tipine uymuyor | TYPE ile anahtarın tipine bakın |
| EXECABORT | Transaction kuyruğa alma hatası yüzünden iptal edildi | QUEUED yerine hata alan komutu bulun |
| NOSCRIPT | EVALSHA ile istenen betik önbellekte yok | SCRIPT LOAD ya da EVAL ile yeniden yükleyin |
| BUSY | Bir betik ya da fonksiyon çok uzun süredir çalışıyor | SCRIPT KILL ya da FUNCTION KILL |
| BUSYKEY | RESTORE var olan bir anahtarı oluşturmak istedi | REPLACE seçeneği ya da başka anahtar adı |
| BUSYGROUP | Tüketici grubu zaten var | Çoğu zaman zararsız; yakalayıp devam edin |
| NOGROUP | Stream ya da tüketici grubu yok | XGROUP CREATE ile MKSTREAM kullanın |
ERR unknown command
Sunucu gönderdiğiniz komutu tanımadığında bu hata gelir. Mesaj, komut adını ve ilk argümanlarını tekrarlar; böylece sunucunun tam olarak ne aldığını görürsünüz. Argümansız bir komutta mesaj komut adıyla biter: ERR unknown command 'FOO'. Alt komutları olan CONFIG gibi komutlar, bilmedikleri bir alt komut için benzer ama farklı bir mesaj döndürür ve yardım komutunu önerir:
> FOO bar
(error) ERR unknown command 'FOO', with args beginning with: 'bar'
> CONFIG FOO
(error) ERR unknown subcommand 'FOO'. Try CONFIG HELP.Belgedeki olası nedenler dört tanedir. Komut adı yanlış yazılmış olabilir. Komut sunucunuzdan daha yeni olabilir; INFO server çıktısındaki redis_version alanına bakın ve gerekiyorsa yükseltin. Hangi komutun hangi sürümle geldiğini Redis 8 yenilikleri yazısında topladık. Komut, sunucunuzun içermediği bir özelliğe ait olabilir: JSON.SET ve FT.SEARCH yalnızca JSON ve Redis Search içeren sunucularda çalışır ve bazı Redis derlemeleri ile paketleri bunları içermez; yüklü modülleri MODULE LIST ile görürsünüz. Son olarak sunucu yapılandırmasındaki rename-command ayarı komutu yeniden adlandırmış ya da kaldırmış olabilir. Transaction içinde bilinmeyen bir komut, EXEC'in de EXECABORT ile başarısız olmasına yol açar.
ERR wrong number of arguments
Komut kabul ettiğinden fazla ya da az argüman aldığında bu hata gelir. Mesaj komut adını küçük harfle verir; alt komutlarda iki adı dikey çizgiyle birleştirir, örneğin 'config|get':
> GET
(error) ERR wrong number of arguments for 'get' command
> CONFIG GET
(error) ERR wrong number of arguments for 'config|get' commandBelgenin listelediği nedenlerden biri özellikle uygulama kodunda sık görülür: boş liste. DEL, MGET ve HSET gibi komutlar en az bir anahtar ya da alan ister. Kodunuz argümanları bir listeden üretiyorsa ve liste boş çıkarsa komut hiç anahtar almadan gider ve bu hatayı verir. Çözüm, komutu göndermeden önce listenin boş olup olmadığını kontrol etmektir. redis-cli'de ise boşluk içeren bir değeri tırnaksız yazmak değeri iki argümana böler: GET my key iki argüman gönderir, doğrusu GET "my key" yazmaktır. Bir de eski sunucu tuzağı var: Redis 6'dan eski sunucular AUTH için yalnızca parola kabul eder, kullanıcı adı ve parola birlikte gönderilirse bu hata alınır.
ERR syntax error

Komut adı doğru ama seçenekler komutun sözdizimine uymuyorsa bu hata gelir. Mesaj hangi seçeneğin yanlış olduğunu söylemez; seçenekleri komut sayfasıyla tek tek karşılaştırmanız gerekir. Belgedeki örnek, birlikte kullanılamayan iki SET seçeneğini gösterir:
> SET mykey "value" NX XX
(error) ERR syntax errorSayfada sayılan tipik nedenler şunlardır: birlikte kullanılamayan seçenekler (SET içinde NX ve XX gibi); yanlış yazılmış ya da sunucunuzun henüz desteklemediği bir seçenek; yanlış yerde duran bir seçenek. Son durum için belge ZADD örneğini verir: NX gibi seçenekler skor ve üyeden önce gelir, yani ZADD myset NX 1 "a" çalışır ama ZADD myset 1 "a" NX bu hatayı verir. Tırnaksız boşluklu değer de bu hataya yol açabilir: SET greeting hello world yazarsanız world ek bir seçenek olarak gider. SET seçeneklerinin ayrıntısı SET, GET ve INCR, ZADD seçenekleri sorted set yazısında.
ERR value is not an integer or out of range
Bir komut tam sayı beklediğinde başka bir şey alırsa bu hata gelir. Sorun gönderdiğiniz argümanda ya da anahtarda saklanan değerde olabilir. INCR anahtardaki sayıya 1 ekler, bu yüzden anahtar metin tutuyorsa başarısız olur; tamsayı olması gereken bir argüman da aynı hatayı verir:
> SET counter "abc"
OK
> INCR counter
(error) ERR value is not an integer or out of range
> EXPIRE counter ten
(error) ERR value is not an integer or out of rangeINCR, DECR, INCRBY ve DECRBY yalnızca 10 ya da -3 gibi tam sayılarla çalışır; 1.5 gibi bir değer de bu hatayı verir ve ondalıklı sayıya ekleme yapmak için INCRBYFLOAT kullanılır. Süre ve sayı gibi argümanlar rakamla yazılmış tam sayılar olmalıdır; 10s ya da 2.5 gibi birim ya da ondalık içeren değerler reddedilir. Redis bu sayıları işaretli 64 bitlik tamsayı olarak saklar, en büyük değer 9223372036854775807'dir. Bir artırma bu sınırı aşacaksa mesaj ERR increment or decrement would overflow olur. Ondalıklı sayı bekleyen INCRBYFLOAT gibi komutlarda ise benzer mesaj ERR value is not a valid float'tur. Süre argümanları için EXPIRE ve TTL yazısına bakın.
WRONGTYPE
Redis'te her anahtar tek bir veri tipi tutar (string, list, hash gibi) ve her komut bu tiplerden yalnızca biriyle çalışır. Anahtarın tipine uymayan bir komut gönderdiğinizde WRONGTYPE Operation against a key holding the wrong kind of value hatası gelir. Bazı komutlar bu hatayı farklı sözcüklerle verir: JSON komutları Existing key has wrong Redis type, HyperLogLog komutları ise HyperLogLog olmayan bir string için WRONGTYPE Key is not a valid HyperLogLog string value. döndürür. Belgedeki örnek ve teşhis adımı:
> RPUSH mylist "a"
(integer) 1
> GET mylist
(error) WRONGTYPE Operation against a key holding the wrong kind of value
> TYPE mylist
listTYPE anahtarın neyi tuttuğunu söyledikten sonra üç olasılıktan birine bakarsınız. Başka bir tipin komutunu kullanmışsınızdır; listeyi okumak için LRANGE, hash alanını okumak için HGET kullanmanız gerekir. Uygulamanın iki farklı parçası aynı anahtar adını farklı veriler için kullanıyordur; her veri türüne kendi önekini verin, örneğin hash'ler için user:, listeler için queue:. Ya da anahtar uygulamanın eski bir sürümünden kalma veriyi tutuyordur; veriye ihtiyacınız yoksa DEL ile silip yeniden yazın. Tip seçimi ve anahtar düzeni için Redis veri tipi seçimi ve anahtar isimlendirme yazılarına bakın.
EXECABORT: transaction neden iptal oldu?

MULTI ile EXEC arasındaki komutlar hemen çalışmaz, kuyruğa alınır ve her biri QUEUED yanıtı döner. Bilinmeyen bir komut adı gibi bir hata içeren komut kuyruğa alınmak yerine reddedilir. Bu durumda EXEC transaction'ı çalıştırmayı reddeder ve hiçbir komut çalışmaz:
> MULTI
OK
> FOO
(error) ERR unknown command 'FOO'
> SET a 1
QUEUED
> EXEC
(error) EXECABORT Transaction discarded because of previous errors.Çözüm, transaction içindeki her komutun yanıtına bakmaktır: QUEUED yerine hata alan komut size neyi düzelteceğinizi söyler. EXEC komutunun kendisi reddedilirse mesaj iki noktadan sonra nedeni verir; örneğin kullanıcının EXEC yetkisi yoksa EXECABORT Transaction discarded because of: NOPERM ... gelir. Önemli bir ayrım: EXEC çalışırken oluşan hatalar transaction'ı iptal etmez. Örneğin bir komut WRONGTYPE alırsa yalnızca o komut başarısız olur, diğerleri çalışır ve EXEC hatayı yanıt listesinde döndürür. Bu, Redis transaction'larında geri alma olmamasının sonucudur ve MULTI, EXEC ve WATCH yazısında ayrıntılı anlatılıyor.
NOSCRIPT ve BUSY: betik hataları
EVALSHA, bir Lua betiğini kaynak kodundan hesaplanan SHA1 özetiyle çalıştırır; sunucu yalnızca daha önce yüklediği betiklerin özetini bilir. Betik önbellekte yoksa NOSCRIPT No matching script. Please use EVAL. hatası gelir:
> EVALSHA ffffffffffffffffffffffffffffffffffffffff 0
(error) NOSCRIPT No matching script. Please use EVAL.Belgenin vurguladığı nokta, betik önbelleğinin verinizle birlikte saklanmamasıdır: sunucu yeniden başladığında, bir replika birincil olduğunda ve biri SCRIPT FLUSH çalıştırdığında boşalır. Bu yüzden kodunuz bu hatayı her an bekleyebilmelidir. NOSCRIPT aldığınızda betiği SCRIPT LOAD ile yükleyin ya da bir kez EVAL ile çalıştırın, sonra EVALSHA çağrısını tekrarlayın. Çoğu istemci bunu kendisi yapar; örneğin redis-py'nin register_script() ile döndürdüğü betik nesnesi bu hatayı alınca betiği yeniden yükler. Alternatif olarak, veriyle birlikte saklanıp replike edilen fonksiyonları kullanabilirsiniz; bkz. Redis Functions ve Lua script ve EVALSHA.
BUSY ise bir Lua betiği ya da fonksiyon busy-reply-threshold süresini (varsayılan 5 saniye) aştığında gelir. Betik çalışırken Redis başka komut çalıştırmaz; diğer istemcileri bekletmek yerine neredeyse her komuta, PING dahil, bu hatayla yanıt verir. Fonksiyonlarda mesaj SCRIPT KILL yerine FUNCTION KILL komutunu önerir; uzun süren bir modül komutu da BUSY Redis is busy running a module command. hatasına yol açar:
> GET mykey
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
> SCRIPT KILL
OKSCRIPT KILL betiği durdurur ve betiği çalıştıran istemci ERR Script killed by user with SCRIPT KILL ile başlayan bir hata alır. Ancak betik veriyi değiştirmeye başlamışsa Redis onu durduramaz, çünkü bu değişikliği yarım bırakmak olur; SCRIPT KILL bu durumda UNKILLABLE ile başarısız olur. Geriye iki seçenek kalır: betiğin bitmesini beklemek ya da sunucuyu SHUTDOWN NOSAVE ile durdurmak. Kalıcı çözüm betiği bu kadar uzun çalışamayacak biçimde değiştirmektir: bitmeyen döngüler ve tek çağrıda çok fazla anahtar ya da eleman işleyen betikler başlıca nedenlerdir; büyük işleri birden çok küçük çağrıya bölün.
BUSYKEY, BUSYGROUP ve NOGROUP
BUSYKEY Target key name already exists. hatası, RESTORE komutu var olan bir anahtarı oluşturmaya çalıştığında gelir. RESTORE, DUMP ile serileştirilmiş bir değerden anahtar oluşturur ve varsayılan olarak var olan anahtarın üzerine yazmaz. Üzerine yazmak istiyorsanız REPLACE seçeneğini ekleyin; mevcut anahtarı korumak istiyorsanız değeri başka bir anahtar adıyla geri yükleyin. Anahtarları başka bir Redis sunucusuna taşıyan MIGRATE komutunda da hedefte var olan anahtarlar için aynı REPLACE seçeneği bulunur.
Stream tüketici gruplarıyla ilgili iki hata birbirinin tersidir. BUSYGROUP Consumer Group name already exists, XGROUP CREATE zaten var olan bir grubu oluşturmaya çalıştığında gelir ve çoğu zaman zararsızdır: birçok uygulama her açılışta grubunu oluşturur, ilk açılıştan sonra grup zaten vardır. Bu durumda hatayı yakalayıp devam etmek yeterlidir. Grubun okumaya başladığı yeri değiştirmek için grubu yeniden oluşturmak yerine XGROUP SETID kullanılır.
> XGROUP CREATE mystream mygroup $ MKSTREAM
OK
> XGROUP CREATE mystream mygroup $ MKSTREAM
(error) BUSYGROUP Consumer Group name already existsNOGROUP ise bir stream komutu var olmayan bir grubu kullandığında gelir. Mesaj hem stream anahtarını hem grubu adlandırır, çünkü ikisinden biri eksik olabilir. XREADGROUP, XPENDING, XCLAIM ve XGROUP CREATECONSUMER bu hatayı döndürebilir. Belgedeki çözümler: grup hiç oluşturulmadıysa tüketiciler okumadan önce XGROUP CREATE ile oluşturun ve stream henüz yoksa MKSTREAM ekleyin; stream silindiyse ya da süresi dolduysa grupları da silinmiştir, grubu yeniden oluşturun; adlar büyük küçük harfe duyarlıdır, mevcut grupları XINFO GROUPS ile listeleyin.
> XREADGROUP GROUP mygroup consumer1 STREAMS mystream >
(error) NOGROUP No such key 'mystream' or consumer group 'mygroup' in XREADGROUP with GROUP optionMKSTREAM olmadan var olmayan bir stream için grup oluşturamazsınız ve ERR The XGROUP subcommand requires the key to exist. ile başlayan bir hata alırsınız. Tüketici gruplarının ayrıntısı consumer group ve XREADGROUP yazısında.
Uygulamada hata yönetimi
Redis'in istemci hata yönetimi sayfası hataları dört kategoriye ayırır: bağlantı hataları, komut hataları, veri hataları ve kaynak hataları. Bu yazıdaki hataların çoğu komut hatası kategorisine girer ve belge bunların genellikle koddaki bir hatayı gösterdiğini, çalışma anında ele almaya çalışmak yerine kodu düzeltmenin doğru olduğunu söyler. İstisna, kullanıcı girdisinden gelen komutlardır; örneğin kullanıcının yazdığı bir JSONPath ifadesi hatalıysa hatayı günlüğe yazıp kullanıcıya varsayılan bir değer ya da açıklama döndürmek mantıklıdır.
Geçici hatalar için ise belge yeniden deneme ve üstel geri çekilme (exponential backoff) kalıbını önerir: zaman aşımları, geçici ağ sorunları ve verinin yüklendiği LOADING durumu bunun tipik örnekleridir. Sayfadaki redis-py örneğini bir fonksiyon içine alarak şöyle uyarlayabilirsiniz:
import time
import redis
def oku(r, key):
max_retries = 3
retry_delay = 0.1
for attempt in range(max_retries):
try:
return r.get(key)
except redis.TimeoutError:
if attempt < max_retries - 1:
time.sleep(retry_delay)
retry_delay *= 2 # üstel geri çekilme
else:
raiseBelge, istemci kütüphanelerinin çoğunun yeniden deneme mantığını zaten içerdiğini, çoğu zaman bunu kendiniz yazmak yerine doğru ayarı vermenin yeteceğini de not eder. Yaygın bir hata da tüm istisnaları tek bir except ile yakalayıp hata türlerini ayırmamaktır: WRONGTYPE bir kod hatasıdır ve yeniden denemekle düzelmez, LOADING ise birkaç saniye sonra kendiliğinden geçer. Bağlantı ve havuz ayarları için bağlantı URL ve connection pool yazısına bakın.
Sunucu tarafında hataları izlemek için INFO errorstats kullanılır: her hata ön eki için errorstat_ERR, errorstat_WRONGTYPE gibi bir satır ve count değeri döner. INFO stats içindeki total_error_replies ise toplam hata yanıtı sayısıdır. Belirli bir hata türünün sayısı birden artmaya başlarsa, yeni dağıtılan bir kod sürümünün yanlış komut gönderdiğinden şüphelenebilirsiniz. Ayrıntı Redis INFO komutu yazısında.
Sık Sorulan Sorular
Hata mesajının tamamı nerede listeleniyor?
Redis belgelerinde yaygın hatalar için ayrı sayfalar ve Redis 8.10'un döndürebileceği tüm hata mesajlarını komutlarıyla birlikte listeleyen bir dizin bulunur; dizin sunucu, Vector set, Search, JSON, olasılıksal tipler ve zaman serisi için ayrı sayfalara bölünmüştür. Bağlantılar yazının sonundaki notta.
ERR syntax error hangi seçeneğin yanlış olduğunu neden söylemiyor?
Belgeye göre mesaj yanlış seçeneği belirtmez. Komutu, komut sayfasındaki sözdizimiyle seçenek seçenek karşılaştırın; özellikle seçeneklerin sırasına, birbirini dışlayan seçeneklere ve sunucunuzun sürümünün o seçeneği destekleyip desteklemediğine bakın.
WRONGTYPE alan anahtarı silmek güvenli mi?
Yalnızca o anahtardaki veriye artık ihtiyacınız olmadığından eminseniz. Önce TYPE ile ne tuttuğuna bakın; sorun iki uygulama parçasının aynı adı kullanmasıysa silmek sorunu yalnızca erteler, anahtar önekleriyle adları ayırmanız gerekir.
BUSYGROUP hatasını görmezden gelebilir miyim?
Grubu her açılışta oluşturan bir uygulamada evet; belge de bu durumda hatayı yakalayıp devam etmeyi önerir. Ancak grubun okuma noktasını değiştirmek istiyorsanız grubu silip yeniden oluşturmak yerine XGROUP SETID kullanın; grubu silmek bekleyen mesaj listesini de siler.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Redis öğrenme rehberi · OOM, MISCONF ve READONLY · CROSSSLOT ve MOVED · NOAUTH ve NOPERM · MULTI ve EXEC · Lua ve EVALSHA