Když bot nefunguje, odpověď je skoro vždy v jeho výpisu. Ukážeme, kde výpis najdete, jak funguje automatický restart, jak chyby zachytit v kódu a co znamenají nejčastější hlášky.
Co budete potřebovat
- Discord bota u StormHostu (nebo na vlastní VPS)
- Přístup do zákaznické zóny
- Bota napsaného v Node.js; ukázky kódu jsou pro discord.js verze 14
- Asi 15 minut
Kde najdete logy#
V zákaznické zóně otevřete Moje služby, klikněte na bota a zůstaňte na záložce Konzole.
- Konzole ukazuje živě všechno, co bot vypisuje:
console.log()aconsole.info()na standardní výstup,console.error()aconsole.warn()na chybový výstup. Výpis padající aplikace (chyba se seznamem souborů a řádků, takzvaný stack trace) uvidíte tady. - Pod konzolí vidíte aktuální využití CPU, RAM, disku a sítě.
- Tlačítka Spustit, Restartovat a Vypnout jsou v záložce Konzole nad samotnou konzolí.
Režim streamu
Konzole bota skrývá IP adresy ve výpisu, jen když je zapnutý režim streamu. Token ani hesla ale za vás neschová. Nikdy je do konzole nevypisujte a nesdílejte snímek obrazovky s nimi. Víc v návodu Zákaznická zóna.
Log do souboru#
Konzole ukazuje jen poslední část výpisu. Když chcete dohledat, co se dělo včera v noci, zapisujte důležité události i do souboru. Jednoduchý pomocník pro CommonJS (require):
const fs = require('node:fs');
const path = require('node:path');
const util = require('node:util');
const slozka = path.join(__dirname, 'logs');
fs.mkdirSync(slozka, { recursive: true });
const soubor = fs.createWriteStream(path.join(slozka, 'bot.log'), { flags: 'a' });
function zapis(uroven, ...casti) {
const radek = `[${new Date().toISOString()}] ${uroven} ${util.format(...casti)}`;
(uroven === 'ERROR' ? console.error : console.log)(radek);
soubor.write(radek + '\n');
}
module.exports = {
info: (...c) => zapis('INFO', ...c),
warn: (...c) => zapis('WARN', ...c),
error: (...c) => zapis('ERROR', ...c),
};| Část | Co dělá |
|---|---|
fs.mkdirSync(slozka, { recursive: true }) | Vytvoří složku logs vedle souboru, pokud neexistuje. |
createWriteStream(…, { flags: 'a' }) | Otevře soubor pro připisování na konec (a = append), staré záznamy zůstanou. |
new Date().toISOString() | Čas události v UTC, například 2026-10-01T18:04:12.345Z. |
util.format(...casti) | Spojí části zprávy stejně jako console.log. U chyby zapíše i výpis řádků (stack trace), u objektu jeho obsah. |
console.error / console.log | Řádek se zároveň objeví v konzoli. |
soubor.write(radek + '\n') | Zapíše řádek do logs/bot.log. |
Použití v botovi: const log = require('./logger'); a pak log.info('Bot je připravený') nebo log.error('Příkaz selhal:', chyba). Soubor logs/bot.log si stáhnete v záložce Soubory. Občas ho smažte nebo vyprázdněte, ať nezaplní disk.
Automatický restart#
Když bot spadne (proces skončí chybou), automaticky se znovu spustí. Krátký výpadek tak často ani nezaznamenáte, ve výpisu konzole ale chybu uvidíte.
- Pokud bot padá hned po startu pořád dokola, chyba je v kódu nebo nastavení a restart ji nevyřeší. Přečtěte si první chybu ve výpisu, opravte ji a bota spusťte tlačítkem Spustit.
- Nepoužívejte v kódu
process.exit()jako běžné ukončení bota. Bot má běžet nepřetržitě. - Restartovat použijte po nahrání nového kódu nebo změně proměnných v záložce Nastavení, změny se projeví až po restartu.
Zachycení chyb, aby bot nepadal#
Node.js ukončí proces při každé chybě, kterou nikdo nezachytí. Patří sem i odmítnutý Promise bez catch (výchozí chování od Node.js 15). Jedna chyba v jednom příkazu tak umí shodit celého bota. Přidejte do hlavního souboru (například index.js) tyto posluchače:
const { Client, Events, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.on(Events.Error, (chyba) => console.error('Chyba klienta discord.js:', chyba));
client.on(Events.Warn, (zprava) => console.warn('Varování discord.js:', zprava));
client.on(Events.ShardError, (chyba) => console.error('Chyba spojení s Discordem:', chyba));
process.on('unhandledRejection', (duvod) => {
console.error('Nezachycená chyba v Promise:', duvod);
});
process.on('uncaughtException', (chyba) => {
console.error('Nezachycená výjimka, bot se ukončí:', chyba);
process.exit(1);
});| Posluchač | Kdy se spustí | Proč ho mít |
|---|---|---|
Events.Error | Klient discord.js ohlásí chybu. | Bez posluchače událost error ukončí proces. |
Events.Warn | Klient hlásí varování. | Upozorní na problém dřív, než něco spadne. |
Events.ShardError | Chyba spojení s bránou Discordu (websocket). | discord.js se znovu připojí sám, vy uvidíte proč. |
unhandledRejection | Promise skončil chybou a nikdo ji nezachytil (chybí await v try nebo .catch()). | Bot nespadne kvůli jedné zapomenuté chybě a vy uvidíte, kde vznikla. |
uncaughtException | Synchronní chyba, kterou nic nezachytilo. | Vypíše chybu a bota ukončí. Po takové chybě není bezpečné pokračovat, automatický restart ho spustí znovu v čistém stavu. |
Chyby v jednotlivých příkazech zachyťte přímo v obsluze interakcí, ať uživatel dostane odpověď a bot běží dál:
const { Events, MessageFlags } = require('discord.js');
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
try {
await zpracujPrikaz(interaction);
} catch (chyba) {
console.error(`Příkaz /${interaction.commandName} selhal:`, chyba);
const odpoved = { content: 'Při provádění příkazu nastala chyba.', flags: MessageFlags.Ephemeral };
if (interaction.replied || interaction.deferred) {
await interaction.followUp(odpoved).catch(console.error);
} else {
await interaction.reply(odpoved).catch(console.error);
}
}
});isChatInputCommand()– zpracovává jen slash příkazy.zpracujPrikaz(– vaše funkce s logikou příkazu.interaction) try { … } catch (chyba) { … }– chyba v příkazu skončí vcatch, ne pádem bota.MessageFlags.Ephemeral– odpověď uvidí jen uživatel, který příkaz zadal.interaction.replied || interaction.deferred– pokud už bot odpověděl nebo odpověď odložil, musí poslat další zprávu přesfollowUp, jinakreply..catch(console.error)– kdyby selhala i chybová odpověď, jen se vypíše.
Paměť#
Bot má k dispozici tolik RAM, kolik dává váš balíček. Když ji spotřebuje, spadne (a automaticky se restartuje), nebo se výrazně zpomalí. Typická hláška při pádu:
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memoryTuto hlášku vypíše sám Node.js, když mu dojde paměť pro objekty JavaScriptu. Když proces ukončí systém kvůli limitu paměti, výpis může skončit i bez chybové hlášky. V obou případech pomůže najít, co paměť zabírá (níže).
Spotřebu sledujte pod konzolí, nebo ji nechte bota vypisovat:
setInterval(() => {
const mb = (b) => Math.round(b / 1024 / 1024);
const m = process.memoryUsage();
console.log(`Paměť: celkem ${mb(m.rss)} MB, heap ${mb(m.heapUsed)}/${mb(m.heapTotal)} MB`);
}, 10 * 60 * 1000);process.memoryUsage()– aktuální spotřeba procesu;rssje celková paměť,heapUsedpaměť objektů JavaScriptu.10 * 60 * 1000– výpis každých 10 minut (hodnota je v milisekundách).
Když paměť pořád roste, nejčastější příčiny jsou:
| Příčina | Řešení |
|---|---|
| discord.js drží v paměti (cache) zprávy, členy a další objekty. U velkých serverů to jsou desítky tisíc položek. | Omezte cache a nechte staré položky mazat (ukázka níže). Nezapínejte intent GuildMembers, pokud ho nepotřebujete, a nenačítejte všechny členy (guild.members.fetch()) bez důvodu. |
| Vlastní pole nebo mapy, které jen rostou (historie, cooldowny, cache výsledků). | Mažte staré položky, nebo data ukládejte do databáze. |
setInterval nebo posluchače událostí přidávané opakovaně (třeba v obsluze příkazu). | Posluchače registrujte jednou při startu. |
Omezení cache v discord.js:
const { Client, GatewayIntentBits, Options } = require('discord.js');
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
makeCache: Options.cacheWithLimits({
...Options.DefaultMakeCacheSettings,
MessageManager: 50,
}),
sweepers: {
...Options.DefaultSweeperSettings,
messages: { interval: 3_600, lifetime: 1_800 },
},
});makeCache: Options.– omezí velikost cache;cacheWithLimits({ … }) MessageManager: 50= nejvýš 50 zpráv na kanál....Options.– ostatní cache ponechá ve výchozím nastavení.DefaultMakeCacheSettings sweepers.messages– každou hodinu (interval: 3_600sekund) smaže z cache zprávy starší než 30 minut (lifetime: 1_800).
Některé cache neomezujte
Dokumentace discord.js varuje, že omezení cache pro GuildManager, ChannelManager, GuildChannelManager, RoleManager a PermissionOverwriteManager není podporované a rozbije funkce knihovny.
Pokud bot po optimalizaci opravdu potřebuje víc paměti, přejděte na větší balíček v záložce Změna balíčku. Doplatíte jen rozdíl do konce období, postup je v článku Prodloužení a upgrade.
Bot na vlastní VPS#
Pokud bota provozujete na VPS, nastavte ho jako službu systemd. Ta zajistí automatický restart i spuštění po restartu VPS a logy uloží do systémového journalu (journalctl -u <NAZEV_SLUZBY> -f). Postup: Aplikace 24/7 přes systemd.
Když něco nefunguje#
Error: Cannot find module 'discord.js'#
Nejsou nainstalované balíčky (chybí složka node_modules, nebo v ní balíček není). Zkontrolujte, že v kořeni projektu je package.json a že má discord.js v části dependencies. Jak se balíčky u nás instalují, popisuje návod Nahrání a spuštění bota.
Error: Cannot find module '…/index.js' nebo './commands/ping.js'#
Node.js nenašel soubor podle cesty:
- Hlavní soubor má jiný název nebo je v podsložce, než čeká nastavení spuštění.
- Velká a malá písmena: Windows je nerozlišuje, server s Linuxem ano.
require(na serveru nenajde složku'. /Commands/ ping. js') commands. Sjednoťte názvy. - Relativní cesta se počítá od souboru, ve kterém je
require, ne od složky, ze které bot startuje. Používejtepath.join(__dirname, …).
Error [ERR_REQUIRE_ESM]: require() of ES Module … not supported#
Načítáte příkazem require() balíček, který existuje jen jako ES modul (například novější verze některých knihoven). Řešení:
- Přejděte v projektu na ES moduly (
import), viz další chyba. - Nebo načtěte balíček dynamicky:
const { default: knihovna } = await import('nazev-balicku');. - Nebo použijte starší verzi balíčku, která ještě podporuje CommonJS.
Novější Node.js (od verze 20.19 a 22.12) umí require() ES modulů načíst a tuto chybu hlásí jen u starších verzí. U modulů s await na nejvyšší úrovni hlásí ERR_REQUIRE_ASYNC_MODULE. Kterou verzi Node.js bot používá, zjistíte podle návodu Verze Node.js.
ReferenceError: require is not defined in ES module scope, you can use import instead#
Projekt je nastavený jako ES moduly ("type": "module" v package.json, nebo soubor s příponou .mjs), ale kód používá require(). Buď přepište require na import (import { Client } from 'discord.js';), nebo z package.json odstraňte "type": "module". V ES modulech také nefunguje __dirname; použijte import.meta.dirname (Node.js 20.11 a novější).
SyntaxError: Cannot use import statement outside a module#
Opak předchozí chyby: kód používá import, ale projekt je CommonJS (typicky "type": "commonjs" v package.json). Do package.json přidejte "type": "module", nebo používejte require(). Kód v jednom projektu nemíchejte.
SyntaxError: Unexpected token (například '?' nebo '.')#
Kód používá syntaxi, kterou verze Node.js na serveru ještě nezná. Zjistěte verzi (console. na začátku bota) a porovnejte ji s požadavky knihoven: discord.js 14 vyžaduje Node.js 18 nebo novější. Postup: Verze Node.js.
Error: Used disallowed intents#
Bot žádá o privilegovaný intent, který nemá v Discord Developer Portalu zapnutý. Otevřete Developer Portal (otevře se v novém okně), svou aplikaci, sekci Bot a v části Privileged Gateway Intents zapněte to, co bot opravdu používá (Presence Intent, Server Members Intent, Message Content Intent). Nebo intent z kódu odstraňte. Podrobně: Token a intenty.
An invalid token was provided. (TokenInvalid)#
Token je špatný, zneplatněný (po Reset Token v Developer Portalu) nebo se do bota vůbec nenačetl (proměnná prostředí je prázdná, soubor .env chybí nebo se nenačítá). Vypište si pro kontrolu jen délku tokenu, nikdy celý token: console.log('Délka tokenu:', process.. Název proměnné použijte ten, který máte v kódu. Postup: Token a intenty.
DiscordAPIError[50013]: Missing Permissions#
Bot nemá oprávnění pro akci (poslat zprávu, přidat roli, smazat zprávu, zabanovat):
- Zkontrolujte role bota v nastavení Discord serveru a oprávnění v daném kanálu (kanál může práva přepsat).
- Pořadí rolí: bot může spravovat jen role, které jsou v seznamu rolí pod jeho nejvyšší rolí. Přetáhněte roli bota výš.
- Vlastníka serveru nemůže bot nijak upravit.
DiscordAPIError[50001]: Missing Access#
Bot nevidí kanál nebo server: nemá v kanálu právo Zobrazit kanál, na serveru vůbec není, nebo registrujete příkazy pro server se špatným ID (bot na něm není). Pokud bota někdo pozval jen s rozsahem bot před delší dobou a registrace příkazů pořád selhává, pozvěte ho znovu odkazem s rozsahy bot a applications.commands.
DiscordAPIError[10062]: Unknown interaction#
Na interakci (slash příkaz, tlačítko) se musí odpovědět do 3 sekund. Když příkaz trvá déle (databáze, API), zavolejte hned na začátku await interaction. a výsledek pošlete později přes interaction.editReply(…). Odložená odpověď platí 15 minut.
Stejnou chybu (nebo DiscordAPIError[40060]: Interaction has already been acknowledged) způsobí i dvě spuštěné kopie bota se stejným tokenem, například u nás a zároveň ve vašem počítači. Obě se snaží odpovědět. Nechte běžet jen jednu.
ECONNRESET, ETIMEDOUT, EAI_AGAIN#
Dočasný výpadek sítě nebo spojení s Discordem. discord.js se k bráně připojí znovu sám a neúspěšné požadavky REST API několikrát zopakuje. Pokud se chyba opakuje dlouhodobě, podívejte se na stav našich služeb a na stav Discordu (discordstatus.com (otevře se v novém okně)).
Bot je pomalý, ve výpisu je 429 nebo rate limit#
Discord omezuje počet požadavků (globálně 50 za sekundu na bota a další limity pro jednotlivé akce). discord.js při překročení automaticky počká a požadavek pošle později, proto bot „zpomalí“. Neposílejte hromadně zprávy, role ani úpravy ve smyčce.
Opakované chybné požadavky = blokace IP adresy
Když bot pošle za 10 minut 10 000 neplatných požadavků (odpovědi 401, 403 nebo 429), Discord IP adresu dočasně zablokuje. Typicky to způsobí smyčka, která pořád zkouší akci bez oprávnění nebo se špatným tokenem. Takovou chybu opravte hned, ne restartem.
Bot je online, ale nereaguje na zprávy#
Pro čtení obsahu zpráv (messageCreate a message.content) potřebuje bot intenty GuildMessages a MessageContent v kódu a zapnutý Message Content Intent v Developer Portalu. Bez něj je message.content prázdné. Pro příkazy raději používejte slash příkazy, které tento intent nepotřebují (první bot v discord.js).
Bot je offline#
- Podívejte se do záložky Konzole: běží bot, nebo je vypnutý? Vypnutého spusťte tlačítkem Spustit.
- Pokud se spustí a hned spadne, přečtěte si první chybu ve výpisu a najděte ji výše.
- Pokud běží bez chyby, ale je offline, zkontrolujte token (resetovaný token = bot se nepřihlásí).
Nic z toho nepomohlo: kdy napsat podpoře#
Napište nám (kontakty), když:
- se konzole nenačte nebo tlačítka Spustit a Restartovat nereagují,
- bot nejde spustit ani s minimálním kódem, který jinde funguje,
- potřebujete jinou verzi Node.js nebo víc paměti.
Pošlete název nebo ID služby, čas problému a přesnou chybovou hlášku (zkopírovaný text z konzole). Nikdy neposílejte token bota.
Shrnutí
- Výpis bota najdete v záložce Konzole, pro historii zapisujte i do souboru.
- Po pádu se bot restartuje sám; když padá hned po startu, oprava je v kódu.
- Posluchače
Events.Error,unhandledRejectionatry/catchv příkazech zabrání pádu kvůli jedné chybě. Used disallowed intentsaTokenInvalidse řeší v Developer Portalu,Missing Permissionsv rolích na Discord serveru.Unknown interaction= pozdní odpověď (použijtedeferReply) nebo dvě běžící kopie bota.