Bir Discord bot hata mesajı genellikle gece yarısı, kullanıcılar en aktifken karşınıza çıkar: bot aniden komutlara cevap vermeyi keser, terminalde uzun bir traceback belirir ve süreç çöker. İyi haber şu ki, bu durumların büyük çoğunluğu önceden tahmin edilebilir ve doğru hata yönetimiyle botunuzu ayakta tutabilirsiniz. Bu yazıda yaygın hata türlerini, komut bazlı try/except kullanımını, global error handler kurulumunu ve düzgün loglamayı hem discord.py hem de discord.js tarafında ele alacağım.
Neden hata yönetimi şart?
Bir bot uzun süre çalışan bir süreçtir. Tek bir komutta yakalanmamış bir istisna (exception), framework'e göre ya o komutu sessizce başarısız bırakır ya da en kötü senaryoda tüm botu düşürür. Kullanıcı tarafında bu, "bot çalışmıyor" şikayetine dönüşür. İyi bir hata yönetimi stratejisi üç şey yapar:
- İzole eder: Tek bir komutun hatası diğer komutları etkilemez.
- Bilgilendirir: Kullanıcıya anlamlı bir mesaj döner, traceback değil.
- Kaydeder: Geliştirici olarak neyin neden bozulduğunu logdan görebilirsiniz.
En sık karşılaşılan hatalar
Hataları yönetmeden önce tanımak gerekir. Pratikte en çok şu türlerle karşılaşırsınız:
- İzin (permission) hataları: Bot bir kanala mesaj göndermeye veya rol vermeye çalışır ama yetkisi yoktur. discord.py'de
discord.Forbidden, discord.js'te50013 Missing Permissions. - Rate limit (429): Çok kısa sürede çok fazla istek. Kütüphaneler bunu genelde otomatik kuyruğa alır, ama döngü içinde mesaj gönderiyorsanız dikkat edin.
- Bulunamayan kaynak (404): Silinmiş bir mesaja tepki vermek, var olmayan bir üyeyi çekmek.
- Geçersiz kullanıcı girdisi: Sayı beklerken metin gelmesi, eksik argüman. discord.py'de
BadArgument/MissingRequiredArgument. - Token/gateway sorunları: Yanlış token, ayrıcalıklı intent'lerin (privileged intents) açılmamış olması.
Komut bazlı try/except
İlk savunma hattı, riskli işlemi doğrudan saran try/except bloğudur. Anahtar nokta: çıplak except: kullanmayın; her zaman beklediğiniz istisna tipini yakalayın, beklenmeyenleri yukarı bırakın ki global handler ve loglar görsün.
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix="!", intents=discord.Intents.default())
@bot.command()
async def kick(ctx, member: discord.Member):
try:
await member.kick(reason="Yönetici kararı")
await ctx.send(f"{member} sunucudan atıldı.")
except discord.Forbidden:
await ctx.send("Bu üyeyi atma yetkim yok.")
except discord.HTTPException as e:
await ctx.send("İşlem sırasında bir ağ hatası oluştu.")
raise # logger ve global handler görsün diye yeniden fırlat
Burada bilinen iki durumu (yetki yok, ağ hatası) kullanıcıya açıklıyoruz; discord.HTTPException dalında ise mesajı verdikten sonra raise ile hatayı tekrar yükselterek loglara düşmesini sağlıyoruz.
Global error handler kurulumu
Her komuta tek tek try/except yazmak sürdürülemez. Bunun yerine merkezi bir hata yakalayıcı tanımlayın. discord.py'de bu on_command_error olayıdır:
import logging
logger = logging.getLogger("bot")
@bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.MissingRequiredArgument):
await ctx.send(f"Eksik argüman: {error.param.name}")
elif isinstance(error, commands.BadArgument):
await ctx.send("Geçersiz değer girdiniz.")
elif isinstance(error, commands.CommandOnCooldown):
await ctx.send(f"Lütfen {error.retry_after:.1f} sn bekleyin.")
elif isinstance(error, commands.MissingPermissions):
await ctx.send("Bu komut için yetkin yok.")
else:
logger.exception("Beklenmeyen hata", exc_info=error)
await ctx.send("Beklenmeyen bir hata oluştu, kaydedildi.")
Slash komutları (app commands) kullanıyorsanız, ayrı bir handler olan tree.on_error ataması yapmanız gerekir; klasik prefix komutlarındaki on_command_error slash komutlarını kapsamaz.
discord.js tarafında mantık benzerdir; istemci olayını dinler ve yakalanmamış reddedilen promise'leri ele alırsınız:
client.on('interactionCreate', async interaction => {
if (!interaction.isChatInputCommand()) return;
try {
await handleCommand(interaction);
} catch (err) {
console.error(err);
const reply = { content: 'Bir hata oluştu.', ephemeral: true };
if (interaction.replied || interaction.deferred) {
await interaction.followUp(reply);
} else {
await interaction.reply(reply);
}
}
});
process.on('unhandledRejection', err => console.error('Unhandled:', err));
Düzgün loglama
print() ile çalışmak başlangıçta cazip görünse de, üretimde işe yaramaz. Python'un yerleşik logging modülünü kullanın: seviyeler (INFO, WARNING, ERROR), zaman damgası ve dosyaya yazma sunar.
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
handlers=[
logging.FileHandler("bot.log", encoding="utf-8"),
logging.StreamHandler(),
],
)
Birkaç pratik tavsiye:
- Hatayı yakaladığınız yerde
logger.exception(...)kullanın; bu, traceback'i otomatik ekler. - Token, şifre gibi sırları asla loglamayın.
- Log dosyalarını döndürün (
RotatingFileHandler) ki disk dolmasın. - Kritik hatalar için ayrı bir Discord webhook kanalına bildirim göndermek, sorunları erken yakalamanın pratik bir yoludur.
Çökmeden ayakta kalma
İyi handler'lara rağmen bot bir gün düşebilir. Bu yüzden süreci bir denetleyici altında çalıştırın: Linux'ta systemd servisi veya pm2 gibi bir process manager, bot kapandığında otomatik yeniden başlatır. Asıl amaç çökmeyi gizlemek değil; logları okuyup kök nedeni düzeltmek, denetleyiciyi ise yalnızca güvenlik ağı olarak görmektir.
Sık Sorulan Sorular
try/except her komutu tek tek sarmalı mıyım?
Hayır. Yalnızca özel kullanıcı mesajı vermek istediğiniz veya bilinen bir riskli işlem (mesaj silme, rol verme) olan yerlerde lokal try/except kullanın. Geri kalan her şey için merkezi on_command_error yeterlidir.
Slash komutlarındaki hatalar neden yakalanmıyor?
Çünkü on_command_error yalnızca prefix komutlarını kapsar. Slash (app) komutları için komut ağacının kendi hata handler'ını (tree.on_error) ayrıca tanımlamanız gerekir.
Rate limit hatası alıyorum, ne yapmalıyım?
Döngü içinde art arda mesaj göndermekten kaçının, toplu işlemleri parçalayın ve kütüphanenin yerleşik kuyruk mekanizmasına güvenin. Manuel sleep ile her isteği yavaşlatmak yerine işlemleri gruplayın.
Botunuz sürekli çöküyor ya da hataları takip edemiyor musunuz? Sağlam bir hata yönetimi ve loglama altyapısı kurup botunuzu üretime hazır hale getirmenize yardımcı olabilirim. Benimle iletişime geçin.