Bir slash komutunu çalıştırdığında karşına çıkan "discord application did not respond" hatası, Discord botlarında en sık rastlanan ama aslında en kolay çözülen sorunlardan biridir. Mesaj çoğu zaman botun "bozuk" olduğunu değil, yanıtı zamanında gönderemediğini anlatır. Discord, bir etkileşime (interaction) ilk yanıtın 3 saniye içinde gelmesini bekler; bu süre dolduğunda botun ne yaptığından bağımsız olarak kullanıcıya bu hatayı gösterir. Bu yazıda hatanın gerçek nedenini, 3 saniye kuralını ve defer ile zamanlamayı doğru kurmanın yollarını adım adım anlatıyorum.
3 saniye kuralı: hatanın asıl sebebi
Bir kullanıcı slash komutu, buton ya da menü kullandığında Discord botuna bir etkileşim gönderir. Bu etkileşimin kısa ömürlü bir "token"ı vardır ve Discord ilk yanıtı 3 saniye içinde bekler. Bu pencerede hiçbir yanıt göndermezsen Discord bağlantıyı geçersiz sayar ve kullanıcıya Application did not respond uyarısını basar. Kodun sonradan başarıyla çalışsa bile artık o etkileşime yanıt veremezsin, çünkü token kapanmıştır.
Önemli ayrım şudur: 3 saniyelik sınır ilk yanıt içindir. İlk yanıtı verdikten sonra (örneğin bir "düşünüyorum" durumu açarak) cevabı düzenlemek için yaklaşık 15 dakikan olur. Yani uzun süren işleri tamamen yapabilirsin; yeter ki Discord'a "yanıt geliyor" sinyalini ilk 3 saniyede ver.
defer ile zaman kazanmak
İşlemin 3 saniyeden uzun sürebileceği her durumda defer kullanmalısın. Defer, Discord'a "yanıtı hazırlıyorum, bekle" der ve kullanıcıya botun yazıyor/düşünüyor göstergesini açar. Bu sayede pencere kapanmaz.
discord.js (v14) ile tipik kullanım şöyledir:
module.exports = {
data: new SlashCommandBuilder()
.setName('istatistik')
.setDescription('Sunucu istatistiklerini getirir'),
async execute(interaction) {
// 3 saniye dolmadan Discord'a haber ver
await interaction.deferReply();
// Uzun sürebilecek iş: veritabanı / API çağrısı
const veri = await istatistikleriGetir(interaction.guildId);
// Hazır olunca ilk yanıtı düzenle
await interaction.editReply(`Toplam üye: ${veri.uyeSayisi}`);
},
};
discord.py tarafında mantık aynıdır, sadece API farklıdır:
@tree.command(name="istatistik", description="Sunucu istatistikleri")
async def istatistik(interaction: discord.Interaction):
await interaction.response.defer() # 3 saniye kuralını karşıla
veri = await istatistikleri_getir(interaction.guild_id)
await interaction.followup.send(f"Toplam üye: {veri['uye_sayisi']}")
reply, editReply ve followUp ne zaman?
Yanıt yöntemlerini karıştırmak da bu hataya veya başka çakışmalara yol açar. Sade bir kural seti işini görür:
- İş hızlıysa (< 3 sn): doğrudan
interaction.reply()kullan, defer'a gerek yok. - İş yavaşsa: önce
deferReply(), sonraeditReply()ile ilk yanıtı doldur. - Ek mesaj göndereceksen: ilk yanıttan sonra
followUp()kullan. - Sadece kullanıcı görsün: defer ederken gizli işaretle. discord.js v14.9+ için
flags: MessageFlags.Ephemeral, eski sürümde{ ephemeral: true }.
Bir etkileşime yalnızca bir kez ilk yanıt verebilirsin. reply() ya da deferReply()'dan sonra tekrar reply() çağırırsan "already been acknowledged" hatası alırsın; o noktadan sonra editReply() veya followUp() kullanılır.
Komutların kayıtlı değilse
Bazen sorun zamanlama değil, komutların Discord'a hiç tanıtılmamış olmasıdır. Eski bir komut tanımı önbellekte kalır, sen yeni kodu yazarsın ama Discord eski tanımı çağırınca kodun ilgili dalına hiç girmez ve yanıt çıkmaz. Komutları her değişiklikte kaydetmen gerekir:
const rest = new REST().setToken(process.env.TOKEN);
await rest.put(
Routes.applicationGuildCommands(CLIENT_ID, GUILD_ID),
{ body: komutlar },
);
console.log('Komutlar kaydedildi.');
Geliştirme sırasında guild (sunucu) komutları kullan; anında güncellenir. Global komutlar tüm sunuculara yayılır ama yayılması zaman alabilir.
Sessiz hataları yakala
En sinsi durum, defer ile editReply arasında bir hata fırlamasıdır. Kod patlar, editReply hiç çalışmaz ve kullanıcı süresiz "düşünüyor" göstergesinde kalır ya da hata mesajını görür. Bu yüzden tüm komut gövdesini try/catch ile sar ve hatayı görünür bir yanıta dönüştür:
async execute(interaction) {
await interaction.deferReply();
try {
const veri = await riskliIslem();
await interaction.editReply(veri.mesaj);
} catch (hata) {
console.error(hata);
await interaction.editReply('Bir şeyler ters gitti, tekrar dener misin?');
}
}
Loglara mutlaka bak: çoğu zaman gerçek hata orada gizlidir (veritabanı zaman aşımı, eksik intent, null değer).
Hızlı kontrol listesi
- Bot gerçekten çevrimiçi mi ve token doğru mu?
- Uzun işlemden önce
deferReply()/defer()çağrıldı mı? - İlk yanıttan sonra
editReply/followUpkullanılıyor mu? - Komutlar Discord'a kaydedildi mi (özellikle guild komutları)?
- Kod
try/catchile korunuyor ve loglar inceleniyor mu? - Gerekli gateway intent'leri etkin mi?
Sık Sorulan Sorular
defer ettim ama hâlâ "application did not respond" alıyorum, neden?
Büyük olasılıkla deferReply() çağrısı 3 saniyeden sonra çalışıyor; örneğin defer'dan önce yavaş bir veritabanı sorgusu var. Defer'ı komutun en başına, ağır işten önce koy. Bir ihtimal de defer çağrısının kendisinin await edilmemesi veya hata vermesidir.
3 saniyeden sonra cevabı düzenlemek için ne kadar zamanım var?
Defer ettikten sonra etkileşim token'ı yaklaşık 15 dakika geçerlidir. Bu süre içinde editReply ve followUp ile yanıt gönderebilirsin. 15 dakikadan uzun işlemler için kalıcı bir mesaj veya kanal mesajı tercih et.
Buton ve menü etkileşimleri de aynı kurala mı tabi?
Evet. Buton, seçim menüsü ve modal gönderimleri de birer etkileşimdir ve aynı 3 saniye kuralına tabidir. İşlem uzun sürecekse onları da defer etmelisin.
Botun hâlâ takılıyor mu? Etkileşim akışını, komut kaydını ve zamanlamayı baştan sona kurup botunu kararlı hale getirebilirim. Benimle iletişime geç, birlikte çözelim.