SQLite hata kodları iki katmandan oluşur: en düşük 8 bit, hatanın genel sınıfını veren birincil sonuç kodudur (ör. SQLITE_CONSTRAINT = 19, SQLITE_BUSY = 5); daha yüksek bitler ise ayrıntıyı veren genişletilmiş sonuç kodunu oluşturur (ör. SQLITE_CONSTRAINT_UNIQUE = 2067). Komut satırı aracı hata mesajının sonunda parantez içinde birincil kodu gösterir; uygulamanızda karar verirken mesaj metnine değil bu kodlara bakmalısınız.
Bu yazıda kodların nasıl okunduğunu, sqlite3 çıktısındaki hata satırlarını, genişletilmiş kodları komut satırında görmenin yolunu ve en sık karşılaşılan mesajların anlamını örneklerle açıklıyoruz. Kilitlenme ve bozulma hataları kendi yazılarında ayrıntılı işlendiği için burada kısaca değinip ilgili yazılara bağlantı veriyoruz.
Sonuç kodu, hata kodu ve genişletilmiş kod
Resmî belge "sonuç kodu" ile "hata kodu" arasında bir ayrım yapar. Sonuç kodları, C arayüzündeki fonksiyonların döndürdüğü tüm sayılardır. Bunlardan yalnızca üçü hata değildir: SQLITE_OK (0) işlemin başarılı olduğunu, SQLITE_ROW (100) bir sonuç satırının hazır olduğunu, SQLITE_DONE (101) ifadenin tamamlandığını bildirir. Geri kalan her kod bir hata kodudur.
Kodlar işaretli 32 bitlik tamsayılardır. Genişletilmiş kod her zaman birincil kodu içinde taşır; birincil kodu bulmak için en düşük 8 biti almak yeterlidir. Aşağıdaki sorgu, bu yazıda karşılaşacağımız genişletilmiş kodların hangi birincil koda ait olduğunu gösteriyor:
SELECT 2067 & 255, 1555 & 255, 1299 & 255, 275 & 255, 517 & 255, 3091 & 255;
-- çıktı: 19|19|19|19|5|19Adlandırma da bu yapıyı yansıtır: birincil kodlar SQLITE_XXX, genişletilmiş kodlar SQLITE_XXX_YYY biçimindedir ve ilk kısım ait oldukları birincil kodu söyler. Belgeye göre mevcut kodların adları ve sayısal değerleri hiç değişmez, ancak yeni sürümlerde yeni kodlar, özellikle yeni genişletilmiş kodlar eklenebilir. Tarihsel uyumluluk nedeniyle C arayüzü varsayılan olarak birincil kodları döndürür; genişletilmiş kod sqlite3_extended_errcode() ile okunur veya bağlantı sqlite3_extended_result_codes() ile genişletilmiş kod döndüren kipe alınır. Dil bağlayıcıları bu bilgiyi farklı adlarla sunar; kullandığınız bağlayıcının belgesine bakın: Python sqlite3, Node.js node:sqlite, PHP PDO.
sqlite3 çıktısındaki hata satırlarını okumak

Aşağıdaki betik, tipik kısıt ve sorgu hatalarını tek seferde üretir. Her ifadenin altına aldığımız mesajı yazdık. Hatalar betiği durdurmadı; son satırdaki sayım yalnızca ilk INSERT'in başarılı olduğunu gösteriyor.
CREATE TABLE uye(
id INTEGER PRIMARY KEY,
eposta TEXT NOT NULL UNIQUE,
yas INTEGER CHECK (yas >= 18)
);
INSERT INTO uye VALUES (1, 'ali@ornek.com', 30);
INSERT INTO uye VALUES (2, 'ali@ornek.com', 25);
-- hata: UNIQUE constraint failed: uye.eposta
INSERT INTO uye VALUES (3, NULL, 25);
-- hata: NOT NULL constraint failed: uye.eposta
INSERT INTO uye VALUES (4, 'can@ornek.com', 12);
-- hata: CHECK constraint failed: yas >= 18
INSERT INTO uye VALUES (1, 'ece@ornek.com', 40);
-- hata: UNIQUE constraint failed: uye.id
CREATE TABLE s(x INTEGER) STRICT;
INSERT INTO s VALUES ('abc');
-- hata: cannot store TEXT value in INTEGER column s.x
SELECT * FROM yok_tablo;
-- hata: no such table: yok_tablo
SELECT ad FROM uye;
-- hata: no such column: ad
INSERT INTO uye(id, eposta) VALUES ('x', 'z@ornek.com');
-- hata: datatype mismatch
SELECT count(*) FROM uye;
-- çıktı: 1Aynı betiği bir dosyadan çalıştırdığınızda komut satırı her hatayı satır numarasıyla birlikte standart hata akışına yazar. Burada iki farklı önek görürsünüz. Parse error, ifade hazırlanırken, yani SQL metni çözümlenip plan oluşturulurken ortaya çıkan hatalardır: olmayan tablo, sütun veya fonksiyon ve söz dizimi hataları bu gruptadır ve araç hatanın yerini bir okla işaretler. Runtime error ise ifade çalışırken oluşur; kısıt ihlalleri, tip uyuşmazlıkları ve kilit hataları bu gruptadır ve sonda parantez içinde birincil kod yazılır.
sqlite3 :memory: < hata.sql # hata.sql: yukarıdaki betik
# Çıktıdan seçilmiş satırlar (standart hata akışı):
# Runtime error near line 7: UNIQUE constraint failed: uye.eposta (19)
# Runtime error near line 16: cannot store TEXT value in INTEGER column s.x (19)
# Parse error near line 18: no such table: yok_tablo
# Parse error near line 20: no such column: ad
# SELECT ad FROM uye;
# ^--- error here
# Runtime error near line 22: datatype mismatch (20)Genişletilmiş kodları .log ile görmek
Komut satırının hata satırı yalnızca birincil kodu gösterir: UNIQUE, NOT NULL ve CHECK ihlallerinin hepsi (19) olarak görünür. Ayrıntıyı görmek için .log stdout komutuyla SQLite'ın hata günlüğünü açabilirsiniz. Günlük satırının başındaki sayı genişletilmiş koddur.
.log stdout
CREATE TABLE uye(id INTEGER PRIMARY KEY, eposta TEXT UNIQUE NOT NULL, yas INTEGER CHECK (yas >= 18));
INSERT INTO uye VALUES (1, 'ali@ornek.com', 30);
INSERT INTO uye VALUES (2, 'ali@ornek.com', 25);
-- çıktı: (2067) abort at 20: UNIQUE constraint failed: uye.eposta; [INSERT INTO uye VALUES (2, 'ali@ornek.com', 25);]
INSERT INTO uye VALUES (1, 'can@ornek.com', 25);
-- çıktı: (1555) abort at 15: UNIQUE constraint failed: uye.id; [INSERT INTO uye VALUES (1, 'can@ornek.com', 25);]
INSERT INTO uye VALUES (3, NULL, 25);
-- çıktı: (1299) abort at 10: NOT NULL constraint failed: uye.eposta; [INSERT INTO uye VALUES (3, NULL, 25);]
INSERT INTO uye VALUES (4, 'ece@ornek.com', 12);
-- çıktı: (275) abort at 13: CHECK constraint failed: yas >= 18; [INSERT INTO uye VALUES (4, 'ece@ornek.com', 12);]Böylece aynı birincil koda düşen dört ihlalin aslında dört ayrı genişletilmiş kod taşıdığını görüyoruz: SQLITE_CONSTRAINT_UNIQUE (2067), SQLITE_CONSTRAINT_PRIMARYKEY (1555), SQLITE_CONSTRAINT_NOTNULL (1299) ve SQLITE_CONSTRAINT_CHECK (275). Satırdaki abort at sayısı sanal makinenin iç adımını gösterir ve sürüme göre değişebilir; ona dayanmayın.
Hata günlüğü yalnızca hataları değil uyarıları da yazar. Aşağıdaki birleştirmede birleştirme sütununda indeks olmadığı için SQLite sorgu sırasında geçici bir otomatik indeks oluşturdu ve bunu SQLITE_WARNING_AUTOINDEX (284) koduyla günlüğe bildirdi. Belge bu uyarının, veritabanının ek bir indeksten fayda görebileceğine işaret ettiğini söyler; indeks tasarımı için SQLite index oluşturma ve EXPLAIN QUERY PLAN yazılarına bakabilirsiniz.
.log stdout
CREATE TABLE siparis(id INTEGER PRIMARY KEY, musteri INTEGER);
CREATE TABLE musteri(no INTEGER, ad TEXT);
INSERT INTO musteri VALUES (1, 'Ayşe'), (2, 'Bora');
INSERT INTO siparis(musteri) VALUES (1), (2), (1);
SELECT count(*) FROM siparis JOIN musteri ON musteri.no = siparis.musteri;
-- çıktı:
-- (284) automatic index on musteri(no)
-- 3
SELECT * FROM yok;
-- çıktı: (1) no such table: yok in "SELECT * FROM yok;"
-- hata: no such table: yokBirincil sonuç kodları
Aşağıdaki tablo, resmî listedeki birincil kodların uygulama geliştirirken karşınıza çıkabilecek olanlarını kısa açıklamalarıyla özetliyor. SQLITE_EMPTY (16) ve SQLITE_FORMAT (24) belgeye göre şu anda kullanılmıyor; SQLITE_NOTICE (27) ve SQLITE_WARNING (28) ise yalnızca hata günlüğünde görünür.
| Kod | Ad | Anlamı |
|---|---|---|
| 1 | SQLITE_ERROR | Daha özel bir kod yoksa kullanılan genel hata (söz dizimi, olmayan tablo vb.) |
| 2 | SQLITE_INTERNAL | İç arıza; çekirdekte veya bir eklentide hata olduğuna işaret eder |
| 3 | SQLITE_PERM | Yeni veritabanı için istenen erişim kipi sağlanamadı |
| 4 | SQLITE_ABORT | İşlem tamamlanmadan durduruldu, çoğunlukla uygulama isteğiyle |
| 5 | SQLITE_BUSY | Başka bir bağlantının etkinliği yüzünden dosyaya erişilemedi |
| 6 | SQLITE_LOCKED | Aynı bağlantı veya paylaşılan önbellek içinde çakışma |
| 7 | SQLITE_NOMEM | Gereken bellek ayrılamadı |
| 8 | SQLITE_READONLY | Yazma izni olmayan bir veritabanına yazma girişimi |
| 9 | SQLITE_INTERRUPT | İşlem sqlite3_interrupt() ile kesildi |
| 10 | SQLITE_IOERR | İşletim sistemi bir G/Ç hatası bildirdi |
| 11 | SQLITE_CORRUPT | Veritabanı dosyası bozuk |
| 13 | SQLITE_FULL | Disk dolu olduğu için yazma tamamlanamadı |
| 14 | SQLITE_CANTOPEN | Veritabanı veya geçici dosya açılamadı |
| 15 | SQLITE_PROTOCOL | WAL kipinde kilitleme protokolü sorunu |
| 17 | SQLITE_SCHEMA | Hazırlanan ifade ile çalıştırma arasında şema değişti |
| 18 | SQLITE_TOOBIG | Metin, BLOB veya SQL ifadesi boyut sınırını aştı |
| 19 | SQLITE_CONSTRAINT | Kısıt ihlali |
| 20 | SQLITE_MISMATCH | Veri tipi uyuşmazlığı |
| 21 | SQLITE_MISUSE | Arayüz tanımsız veya desteklenmeyen biçimde kullanıldı |
| 23 | SQLITE_AUTH | Yetkilendirme geri çağrısı ifadeyi reddetti |
| 25 | SQLITE_RANGE | Bağlama parametresi veya sütun numarası aralık dışında |
| 26 | SQLITE_NOTADB | Açılan dosya bir SQLite veritabanı gibi görünmüyor |
Sık görülen mesajlar ve çözümleri

constraint failed mesajları
UNIQUE constraint failed, NOT NULL constraint failed, CHECK constraint failed ve FOREIGN KEY constraint failed mesajlarının hepsi SQLITE_CONSTRAINT ailesindendir. Mesaj ihlal edilen sütunu veya CHECK ifadesini söyler. Yinelenen kayıt beklenen bir durumsa hatayı yakalamak yerine UPSERT ve ON CONFLICT yazısındaki yöntemleri kullanın. Bir tetikleyici içindeki RAISE() çağrısı da kendi mesajınızla aynı aileden SQLITE_CONSTRAINT_TRIGGER üretir. STRICT tablolarda yanlış tipte değer ise cannot store TEXT value in INTEGER column mesajıyla SQLITE_CONSTRAINT_DATATYPE (3091) verir; ayrıntı için STRICT tablolar yazısına bakın.
PRAGMA foreign_keys = ON;
CREATE TABLE yazar(id INTEGER PRIMARY KEY, ad TEXT);
CREATE TABLE kitap(id INTEGER PRIMARY KEY, yazar_id INTEGER REFERENCES yazar(id));
INSERT INTO kitap VALUES (1, 99);
-- hata: FOREIGN KEY constraint failed
CREATE TRIGGER yazar_sil BEFORE DELETE ON yazar
BEGIN
SELECT RAISE(ABORT, 'yazarı silmeden önce kitaplarını taşıyın');
END;
INSERT INTO yazar VALUES (1, 'Orhan');
DELETE FROM yazar WHERE id = 1;
-- hata: yazarı silmeden önce kitaplarını taşıyın
SELECT bilinmeyen_fonksiyon(1);
-- hata: no such function: bilinmeyen_fonksiyon
SELECT 1 UNION SELECT;
-- hata: near ";": syntax error
SELECT length(zeroblob(1000000001));
-- hata: string or blob too bigdatatype mismatch
SQLite normalde tip konusunda çok esnektir; SQLITE_MISMATCH (20) yalnızca katı olduğu birkaç durumda görülür. Belgede verilen tipik örnek rowid'dir: rowid tamsayı olmak zorundadır ve tamsayıya çevrilemeyen bir değer atamak bu hatayı verir. Yukarıdaki ilk betikte INTEGER PRIMARY KEY sütununa 'x' yazmaya çalıştığımızda aldığımız hata budur. Rowid ile birincil anahtar ilişkisi PRIMARY KEY ve rowid yazısında anlatılıyor.
no such table, no such column, syntax error
Bu mesajlar SQLITE_ERROR (1) ile gelir ve ifade hazırlanırken oluşur. no such table aldığınızda yanlış dosyayı açmış olabilirsiniz: SQLite olmayan bir dosya adı verildiğinde yeni, boş bir veritabanı oluşturur ve tablo bulunamaz. Komut satırında .databases ile açık dosyanın yolunu, tabloları listeleme yazısındaki yöntemlerle tabloları kontrol edin. Tırnak kullanımında da dikkat edin: tanımlayıcılar için çift tırnak, metin değerleri için tek tırnak kullanılır.
attempt to write a readonly database
SQLITE_READONLY (8) dosyanın salt okunur açıldığını veya bağlantının yazma izni olmadığını söyler. Genişletilmiş kodlar nedeni daraltır: SQLITE_READONLY_DIRECTORY sürecin veritabanının bulunduğu dizinde günlük dosyası oluşturamadığını, SQLITE_READONLY_DBMOVED dosyanın açıldıktan sonra taşındığını, SQLITE_READONLY_ROLLBACK geri alınması gereken bir sıcak günlük bulunduğunu ama dosyanın salt okunur olduğunu, SQLITE_READONLY_RECOVERY ise WAL kurtarmasının yazma izni gerektirdiğini belirtir. Sunucularda en sık neden, web sunucusu kullanıcısının dosyaya izni olduğu hâlde dizine yazma izni olmamasıdır.
sqlite3 notdb.db < sorgu.sql
# Parse error near line 1: file is not a database (26)
sqlite3 -readonly ro.db < ekle.sql
# Runtime error near line 1: attempt to write a readonly database (8)
sqlite3 yok_klasor/x.db < sorgu.sql
# Error: unable to open database "yok_klasor/x.db": unable to open database fileunable to open database file ve file is not a database
SQLITE_CANTOPEN (14) dosyanın açılamadığını söyler: dizin yoktur, yol bir dizini gösteriyordur (SQLITE_CANTOPEN_ISDIR) ya da izin yoktur. Bu hata yalnızca ana dosya için değil geçici dosyalar için de oluşabilir. SQLITE_NOTADB (26) ise dosyanın açıldığını ama başlığının SQLite biçiminde olmadığını gösterir; yanlış dosya, şifrelenmiş bir veritabanı veya bozulma olabilir. Bozulma şüphesinde bozuk veritabanı kurtarma yazısındaki adımları izleyin.
database or disk is full ve string or blob too big
SQLITE_FULL (13) yalnızca ana dosya değil geçici dosyalar yazılırken de ortaya çıkabilir. Belge, ana diskte bol yer olduğu hâlde bu hatayı alan uygulamaların genellikle geçici dosyaların daha küçük bir bölümde tutulduğu sistemlerde çalıştığını belirtir. SQLITE_TOOBIG (18) ise bir metin veya BLOB değerinin, ya da SQL ifadesinin, boyut sınırını aştığını söyler; her ikisi için varsayılan sınır 1.000.000.000 bayttır.
database is locked ve database disk image is malformed
SQLITE_BUSY (5) ve SQLITE_CORRUPT (11) en çok soru getiren iki koddur ve ayrı yazılarda ele alınıyor: kilit modeli, bekleme süresi ve WAL için database is locked hatası, bozulma nedenleri ve kurtarma için bozuk veritabanı kurtarma.
İşlem içinde hata: ne geri alınır?
Bir kısıt ihlali olduğunda varsayılan çakışma çözümü ABORT'tur. Belgeye göre ABORT yalnızca hatayı veren ifadenin yaptığı değişiklikleri geri alır; aynı işlem içindeki önceki ifadelerin değişiklikleri durur ve işlem açık kalır. Bu, para transferi gibi işlemlerde ciddi bir tuzaktır. Aşağıdaki örnekte üçüncü UPDATE başarısız oldu, ama işlem açık kaldığı için ilk iki UPDATE'in etkisi görünmeye devam etti; tutarlılığı ancak açık bir ROLLBACK geri getirdi.
CREATE TABLE hesap(id INTEGER PRIMARY KEY, bakiye INTEGER CHECK (bakiye >= 0));
INSERT INTO hesap VALUES (1, 100), (2, 50);
BEGIN;
UPDATE hesap SET bakiye = bakiye + 80 WHERE id = 2;
UPDATE hesap SET bakiye = bakiye - 80 WHERE id = 1;
UPDATE hesap SET bakiye = bakiye - 80 WHERE id = 1;
-- hata: CHECK constraint failed: bakiye >= 0
SELECT id, bakiye FROM hesap; -- işlem hâlâ açık, ilk iki UPDATE duruyor
-- çıktı:
-- 1|20
-- 2|130
ROLLBACK;
SELECT id, bakiye FROM hesap;
-- çıktı:
-- 1|100
-- 2|50Uygulama kodunda kural basittir: işlem içindeki herhangi bir ifade hata verdiyse, hatayı kaydedip işlemin tamamını geri alın. UNIQUE, NOT NULL ve PRIMARY KEY kısıtlarında ON CONFLICT ROLLBACK tanımlamak da bir seçenektir; bu durumda ihlal tüm işlemi geri alır. Belgeye göre ON CONFLICT yan tümcesi CHECK ve yabancı anahtar kısıtlarında kullanılamaz, bu yüzden yukarıdaki örnekte tek yol açık ROLLBACK'tir. Çakışma algoritmalarının farkları UPSERT ve transaction yazılarında anlatılıyor.
Betiklerde de benzer bir karar vermeniz gerekir. Komut satırı aracı varsayılan olarak hatadan sonra betiğin kalanını çalıştırmaya devam eder ve sonunda 1 çıkış koduyla döner. -bail seçeneği veya betiğin başına yazılan .bail on ise ilk hatada durur. Şema göçü gibi adımların sırasının önemli olduğu betiklerde durmak genellikle daha güvenlidir; göç betikleri için şema göçü yazısına bakın.
-- bail.sql
CREATE TABLE t(id INTEGER PRIMARY KEY);
INSERT INTO t VALUES (1);
INSERT INTO t VALUES (1);
SELECT 'bu satır çalıştı mı?';sqlite3 :memory: < bail.sql; echo $?
# Runtime error near line 4: UNIQUE constraint failed: t.id (19)
# bu satır çalıştı mı?
# 1
sqlite3 -bail :memory: < bail.sql; echo $?
# Runtime error near line 4: UNIQUE constraint failed: t.id (19)
# 1Uygulamada hata işleme önerileri
- Mesaj metnine göre dallanmayın: Mesajlar insan içindir ve değişebilir; koda, gerekiyorsa genişletilmiş koda bakın.
- Önce birincil kodu sınıflandırın: Genişletilmiş kodun en düşük 8 biti birincil koddur; bilmediğiniz yeni bir genişletilmiş kod gelse bile birincil kod üzerinden doğru davranışı seçebilirsiniz.
- Yeniden denenebilir hataları ayırın:
SQLITE_BUSYgenellikle kısa bir beklemeden sonra işlemin baştan alınmasıyla çözülür;SQLITE_CONSTRAINTise yeniden denemeyle düzelmez. - SQLITE_MISUSE gördüyseniz kodu düzeltin: Belgeye göre bu kod uygulamanın yanlış yazıldığını gösterir ve tespiti olasılığa dayalıdır; ona güvenen bir akış kurmayın.
- SQLITE_SCHEMA için:
sqlite3_prepare_v2()ile hazırlanan ifadeler şema değişince otomatik olarak yeniden hazırlanır (varsayılan en fazla 50 deneme). Eskisqlite3_prepare()kullanan kodlarda bu hatayı kendiniz ele almanız gerekir.
Sık Sorulan Sorular
Komut satırındaki (19) sayısı ne anlama gelir?
Hatanın birincil sonuç kodudur; 19, SQLITE_CONSTRAINT demektir. Hangi kısıtın ihlal edildiğini mesaj metni veya .log ile görülen genişletilmiş kod söyler.
Genişletilmiş koddan birincil kodu nasıl bulurum?
En düşük 8 biti alın: SQL içinde kod & 255, çoğu programlama dilinde de aynı bit işlemiyle. Örneğin 2067 için sonuç 19'dur.
Parse error ile Runtime error arasındaki fark nedir?
Parse error ifade hazırlanırken, yani çalışmaya başlamadan önce oluşur ve veride değişiklik yapılmamıştır. Runtime error ifade çalışırken oluşur; varsayılan ABORT davranışında o ifadenin değişiklikleri geri alınır, ama açık bir işlem varsa önceki ifadelerin değişiklikleri kalır.
SQLITE_INTERNAL hatası alırsam ne yapmalıyım?
Belgeye göre çalışan bir SQLite sürümünde bu kod hiç görülmemelidir. Çekirdekteki bir hataya işaret edebilir, ama uygulamanın tanımladığı SQL fonksiyonları, sanal tablolar, VFS katmanları veya diğer eklentiler de bu kodu üretebilir. Önce kullandığınız eklentileri devre dışı bırakarak sorunu yalıtın.
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: SQLite öğrenme rehberi · SQLite database is locked hatası · SQLite bozuk veritabanı kurtarma · SQLite CREATE TABLE ve kısıtlamalar · SQLite UPSERT · SQLite transaction