Vercel Deploy Sonrası 404 NOT_FOUND: Sebepler ve Çözümler
Build logu yeşil, deployment "Ready" diyor, sayfa ise 404: NOT_FOUND. Aradığınızda çoğunlukla her birinde farklı sebep çıkan forum başlıkları bulursunuz; asıl sorun da bu: "deploy sonrası 404" en az dört ilgisiz kaynaktan gelebilen bir belirti. Bu yazı onları, kontrol edeceğim sırayla diziyor.
Aşağıdaki Vercel bilgilerinin hepsi Kasım 2026'da okunan dokümantasyondan; Next.js kısımları Next.js 16 dokümanından. Burada kendi yaşadığım bir olayı anlatmıyorum; yazı dokümandan çıkarılmış bir kontrol listesi.
Hata gerçekte ne diyor
Vercel NOT_FOUND'u, istenen kaynağın bulunamadığında oluşan hata olarak tanımlıyor; örneğin taşınmış ya da silinmiş olabilir ya da URL'de yazım hatası vardır. Yakın akrabası DEPLOYMENT_NOT_FOUND, var olmayan bir deployment'a yapılan istek için (yanlış deployment URL'si ya da kimliği, ya da deployment silinmiş).
Dokümandaki sorun giderme adımları kısa:
- Deployment URL'sinde yazım hatası ya da yanlış yol olup olmadığına bakın.
- Deployment'ın var olduğunu ve silinmediğini doğrulayın.
- Varsa deployment loglarını okuyun.
- Erişim izniniz olduğunu kontrol edin.
İlk dakika için doğru liste bu. Yazının kalanı, dördü de geçtiği halde başarıyla build olmuş bir deployment'ta hâlâ 404 aldığınız durum için.
Adım 1: 404'ü platform mu verdi, uygulamanız mı?
Tam URL'yi tarayıcıda açın ve sayfaya bakın.
NOT_FOUNDkodlu Vercel'in kendi hata sayfası: platform o yol için sunacak bir şey bulamadı. Uygulamanız hiç çalışmadı. 2. ve 3. adıma gidin.- Kendi 404 sayfanız: platform isteği uygulamanıza yönlendirdi, uygulamanız o rotanın olmadığına karar verdi. 5. adıma gidin.
Bundan sonrasının hepsini bu ayrım belirliyor ve çoğu başlık bu soruyu atlıyor.
Adım 2: output directory ve framework preset
Vercel build dokümanı, statik olarak yalnızca Output Directory içeriğinin sunulduğunu söylüyor. Vercel bir framework algılarsa output directory otomatik ayarlanır. Algılamazsa Framework Preset "Other" olur ve "Other" için doküman şunu söylüyor: public klasörü varsa output directory odur, yoksa . (proje kökü).
Bu, başarılı build'e rağmen 404 almanın iki yaygın yolunu veriyor:
- Preset yanlış ya da framework gerektiren projede "Other".
distya dabuildklasörüne yazan bir build'in output directory'si başka yeri gösteriyorsa,/index.htmldiye bulunacak bir şey yoktur. Settings, sonra Build and Deployment'a girip Framework Preset ve Output Directory'yi build komutunuzun gerçekten yazdığı yerle karşılaştırın. - Eski override. Doküman, değişen bir Override ayarının sonraki deployment'tan itibaren geçerli olduğunu belirtiyor. Ayarı düzeltip eski deployment'ı denediyseniz eski davranışı görüyorsunuzdur. Yeniden deploy edin.
Bunları vercel.json içinde framework ve outputDirectory alanlarıyla deployment bazında da sabitleyebilirsiniz; bu alanlar o deployment için proje ayarını ezer. Depodaki vercel.json panelle çelişiyorsa şüphelenilecek olan dosyadır.
Monorepo'da Root Directory
Uygulama bir alt klasördeyse projenin Root Directory'si oraya işaret etmeli. Gerçek uygulama alt klasördeyken Root Directory depo köküne ayarlıysa, niyet ettiğinizden başka bir şey build edilir. Doküman ayrıca varsayılan olarak açık olan "Include files outside the root directory in the Build Step" anahtarını anlatıyor; build'in o dizin dışındaki dosyalara erişmesini sağlıyor. Kapatırsanız build erişemez.
Adım 3: statik site, rotada yenileyince 404
Tek sayfa uygulamaların (SPA) klasik sorunu: ana sayfa açılıyor, /about'a tıklayınca çalışıyor, yenileyince NOT_FOUND geliyor. İstemci tarafı yönlendirmeli bir SPA'da gerçek dosya yalnızca index.html; /about sadece JavaScript yönlendiricisinin içinde var.
Vercel'in vercel.json dokümanı tam bu durum için yedek rewrite'ı veriyor ("sıklıkla Single Page Application için kullanılır"):
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}Aynı sayfadan iki ayrıntı önemli:
- Doküman, rewrite'lar uygulanmadan önce dosya sistemine öncelik verildiğini söylüyor; yani JavaScript paketleriniz gibi gerçek dosyalar yine dosya olarak sunulur, rewrite yalnızca hiçbir dosyayla eşleşmeyen yolları yakalar.
- Redirect'ler rewrite'lardan önce işlenir. Aynı yolla eşleşen bir
redirectskuralınız da varsa o kazanır.
Bu çözüm statik SPA içindir. Next.js gibi kendi sunucu tarafı yönlendirmesi olan bir framework'te gerekmez.
Adım 4: sondaki slash ve yol farkları
/docs çalışıp /docs/ çalışmıyorsa (ya da tersi) vercel.json içindeki trailingSlash'e bakın. Doküman, trailingSlash: false iken slash ile biten yolun slash'sız sürüme 308 ile yönlendirildiğini söylüyor. Bu bir yönlendirme, 404 değil; yani formlardan birinde gerçek 404 görüyorsanız sebep slash ayarı değil, eksik bir dosya ya da rotadır.
Adım 5: 404'ü Next.js uygulamanız verdi
404 sayfası sizinse platform işini yapmış, uygulama "yok" demiş demektir. App Router'da bunun dokümanda geçen birkaç yolu var:
notFound()fırlatıldı. Bir rota segmentindenotFound()çağırmak en yakınnot-founddosyasını render eder. Tipik örüntü, istenen slug için hiçbir şey döndürmeyen bir veri sorgusudur. Canlıdaki veri yerelden farklıysa (boş veritabanı, eksik ortam değişkeni, "sonuç yok" sayılan başarısız bir fetch), build geçtiği halde her dinamik sayfa 404 verir. Rotadan şüphelenmeden önce sorgunun ne döndürdüğünü loglayın.- Rota hiçbir dosyayla eşleşmiyor. Eşleşmeyen URL uygulamanın 404'ünü alır.
appaltındaki gerçek klasör adlarını, büyük/küçük harf dahil kontrol edin; büyük-küçük harfe duyarsız bir dizüstü dosya sisteminde çalışan uyuşmazlık Linux build'inde çalışmaz. dynamicParams = false. Varsayılantrue'dur; yanigenerateStaticParamsile üretilmemiş dinamik segment isteğe göre render edilir.falseyaparsanız yalnızca önceden üretilen parametreler vardır, diğer her değer 404 verir. Cache Components açıkken bu seçenek kullanılamaz.
Hata ayıklamayı karıştıran bir Next.js ayrıntısı daha: not-found sayfası stream edildiğinde HTTP durumu 404 değil 200 olur ve Next.js bunun yerine HTML'e noindex robots meta etiketi ekler. Doküman, notFound çalıştığında başlıkların zaten gönderilmiş olduğunu açıklıyor. Yani "sayfa Not Found gösteriyor ama durum kodu 200" dokümante edilmiş bir davranış, Vercel hatası değil. Gerçek bir 404 durumu gerekiyorsa doküman, kaynağın gövde stream edilmeden önce var olduğunu doğrulamanızı söylüyor; örneğin proxy içinde bir kontrolle.
Tüm uygulamada eşleşmeyen URL için Next.js 16'da experimental.globalNotFound arkasında deneysel bir global-not-found.js var. Doküman normal render'ı atladığını söylüyor, yani kendi global stillerinizi ve fontlarınızı içine almanız gerekir. Uygulamanızda birden çok kök layout ya da dinamik segment üzerine kurulu bir kök layout yoksa (dokümanın bunun için andığı iki durum) dokunmazdım.
Adım 6: logları okuyun, sonra domain'in neyi gösterdiğine bakın
Platform hata sayfası çıkıyor ve ayarlar doğru görünüyorsa deployment'ın build loglarında build'in gerçekte ne ürettiğine bakın ve yapılandırdığınız Output Directory ile karşılaştırın.
Deployment URL'si ile production domain'inin farklı şeyler olduğunu da aklınızda tutun. Yeni build ettiğiniz deployment sağlam olabilirken ziyaret ettiğiniz domain eski bir deployment'ı ya da kaldırılmış bir deployment'ı sunuyor olabilir. Önce üretilen deployment URL'sini doğrudan deneyin; o çalışıp domain çalışmıyorsa sorun build'inizde değil domain atamasında. Domain kurulumunu bu yazıda ele almadım.
Kısa kontrol sırası
- URL doğru mu, deployment var mı?
- Platform hata sayfası mı, kendi 404 sayfanız mı?
- Framework Preset, Output Directory, Root Directory: build'in ürettiğiyle uyuşuyor mu? Değiştirdikten sonra yeniden deploy edin.
- Statik SPA: yedek rewrite ekleyin.
- Next.js:
notFound()arkasındaki sorguyu loglayın, klasör adlarına vedynamicParams'a bakın. - Build sorunu ile domain sorununu ayırmak için üretilen deployment URL'sini doğrudan açın.
Özet
Yeşil bir build'e rağmen Vercel 404'ü neredeyse hiç tek bir sorun değildir. En faydalı tek soru 404'ü kimin verdiği: Vercel'in platform sayfası sunulacak bir şey bulunamadı demektir (preset, output directory, root directory, SPA rewrite'ına bakın); kendi sayfanız ise uygulamanızın çalışıp "yok" dediği anlamına gelir (notFound() ve rota dosyalarına bakın). Ayar değişiklikleri yalnızca sonraki deployment'ta geçerli olur; bu yüzden bir düzeltmenin işe yaramadığına karar vermeden önce yeniden deploy edin.