Keď bot nefunguje, odpoveď je takmer vždy v jeho výpise. Ukážeme, kde výpis nájdete, ako funguje automatický reštart, ako chyby zachytiť v kóde a čo znamenajú najčastejšie hlásenia.
Čo budete potrebovať
- Discord bota u StormHostu (alebo na vlastnom VPS)
- Prístup do zákazníckeho účtu
- Bota napísaného v Node.js; ukážky kódu sú pre discord.js verzie 14
- Približne 15 minút
Kde nájdete logy#
V zákazníckom účte otvorte Moje služby, kliknite na bota a zostaňte na záložke Konzola.
- Konzola ukazuje naživo všetko, čo bot vypisuje:
console.log()aconsole.info()na štandardný výstup,console.error()aconsole.warn()na chybový výstup. Výpis padajúcej aplikácie (chyba so zoznamom súborov a riadkov, takzvaný stack trace) uvidíte tu. - Pod konzolou vidíte aktuálne využitie CPU, RAM, disku a siete.
- Tlačidlá Spustiť, Reštartovať a Vypnúť sú v záložke Konzola nad samotnou konzolou.
Režim streamu
Konzola bota skrýva IP adresy vo výpise, iba keď je zapnutý režim streamu. Token ani heslá však za vás neschová. Nikdy ich do konzoly nevypisujte a nezdieľajte snímku obrazovky s nimi. Viac v návode Zákaznícky účet.
Log do súboru#
Konzola ukazuje iba poslednú časť výpisu. Keď chcete dohľadať, čo sa dialo včera v noci, zapisujte dôležité udalosti aj do súboru. Jednoduchý pomocník pre 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),
};| Časť | Čo robí |
|---|---|
fs.mkdirSync(slozka, { recursive: true }) | Vytvorí priečinok logs vedľa súboru, ak neexistuje. |
createWriteStream(…, { flags: 'a' }) | Otvorí súbor na pripisovanie na koniec (a = append), staré záznamy zostanú. |
new Date().toISOString() | Čas udalosti v UTC, napríklad 2026-10-01T18:04:12.345Z. |
util.format(...casti) | Spojí časti správy rovnako ako console.log. Pri chybe zapíše aj výpis riadkov (stack trace), pri objekte jeho obsah. |
console.error / console.log | Riadok sa zároveň objaví v konzole. |
soubor.write(radek + '\n') | Zapíše riadok do logs/bot.log. |
Použitie v botovi: const log = require('./logger'); a potom log.info('Bot je pripravený') alebo log.error('Príkaz zlyhal:', chyba). Súbor logs/bot.log si stiahnete v záložke Súbory. Občas ho zmažte alebo vyprázdnite, aby nezaplnil disk.
Automatický reštart#
Keď bot spadne (proces skončí chybou), automaticky sa znova spustí. Krátky výpadok tak často ani nezaznamenáte, vo výpise konzoly však chybu uvidíte.
- Ak bot padá hneď po štarte stále dokola, chyba je v kóde alebo nastavení a reštart ju nevyrieši. Prečítajte si prvú chybu vo výpise, opravte ju a bota spustite tlačidlom Spustiť.
- Nepoužívajte v kóde
process.exit()ako bežné ukončenie bota. Bot má bežať nepretržite. - Reštartovať použite po nahraní nového kódu alebo zmene premenných v záložke Nastavenia, zmeny sa prejavia až po reštarte.
Zachytenie chýb, aby bot nepadal#
Node.js ukončí proces pri každej chybe, ktorú nikto nezachytí. Patrí sem aj odmietnutý Promise bez catch (predvolené správanie od Node.js 15). Jedna chyba v jednom príkaze tak dokáže zhodiť celého bota. Pridajte do hlavného súboru (napríklad index.js) týchto poslucháčov:
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('Varovanie discord.js:', zprava));
client.on(Events.ShardError, (chyba) => console.error('Chyba spojenia s Discordom:', chyba));
process.on('unhandledRejection', (duvod) => {
console.error('Nezachytená chyba v Promise:', duvod);
});
process.on('uncaughtException', (chyba) => {
console.error('Nezachytená výnimka, bot sa ukončí:', chyba);
process.exit(1);
});| Poslucháč | Kedy sa spustí | Prečo ho mať |
|---|---|---|
Events.Error | Klient discord.js ohlási chybu. | Bez poslucháča udalosť error ukončí proces. |
Events.Warn | Klient hlási varovanie. | Upozorní na problém skôr, než niečo spadne. |
Events.ShardError | Chyba spojenia s bránou Discordu (websocket). | discord.js sa znova pripojí sám, vy uvidíte prečo. |
unhandledRejection | Promise skončil chybou a nikto ju nezachytil (chýba await v try alebo .catch()). | Bot nespadne kvôli jednej zabudnutej chybe a vy uvidíte, kde vznikla. |
uncaughtException | Synchrónna chyba, ktorú nič nezachytilo. | Vypíše chybu a bota ukončí. Po takej chybe nie je bezpečné pokračovať, automatický reštart ho spustí znova v čistom stave. |
Chyby v jednotlivých príkazoch zachyťte priamo v obsluhe interakcií, aby používateľ dostal odpoveď a bot bežal ďalej:
const { Events, MessageFlags } = require('discord.js');
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
try {
await zpracujPrikaz(interaction);
} catch (chyba) {
console.error(`Príkaz /${interaction.commandName} zlyhal:`, chyba);
const odpoved = { content: 'Pri vykonávaní prí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()– spracúva iba slash príkazy.zpracujPrikaz(– vaša funkcia s logikou príkazu.interaction) try { … } catch (chyba) { … }– chyba v príkaze skončí vcatch, nie pádom bota.MessageFlags.Ephemeral– odpoveď uvidí iba používateľ, ktorý príkaz zadal.interaction.replied || interaction.deferred– ak už bot odpovedal alebo odpoveď odložil, musí poslať ďalšiu správu cezfollowUp, inakreply..catch(console.error)– keby zlyhala aj chybová odpoveď, iba sa vypíše.
Pamäť#
Bot má k dispozícii toľko RAM, koľko dáva váš balík. Keď ju spotrebuje, spadne (a automaticky sa reštartuje), alebo sa výrazne spomalí. Typické hlásenie pri páde:
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memoryToto hlásenie vypíše sám Node.js, keď mu dôjde pamäť pre objekty JavaScriptu. Keď proces ukončí systém kvôli limitu pamäte, výpis môže skončiť aj bez chybového hlásenia. V oboch prípadoch pomôže nájsť, čo pamäť zaberá (nižšie).
Spotrebu sledujte pod konzolou, alebo ju nechajte bota vypisovať:
setInterval(() => {
const mb = (b) => Math.round(b / 1024 / 1024);
const m = process.memoryUsage();
console.log(`Pamäť: celkom ${mb(m.rss)} MB, heap ${mb(m.heapUsed)}/${mb(m.heapTotal)} MB`);
}, 10 * 60 * 1000);process.memoryUsage()– aktuálna spotreba procesu;rssje celková pamäť,heapUsedpamäť objektov JavaScriptu.10 * 60 * 1000– výpis každých 10 minút (hodnota je v milisekundách).
Keď pamäť stále rastie, najčastejšie príčiny sú:
| Príčina | Riešenie |
|---|---|
| discord.js drží v pamäti (cache) správy, členov a ďalšie objekty. Pri veľkých serveroch sú to desaťtisíce položiek. | Obmedzte cache a nechajte staré položky mazať (ukážka nižšie). Nezapínajte intent GuildMembers, ak ho nepotrebujete, a nenačítavajte všetkých členov (guild.members.fetch()) bez dôvodu. |
| Vlastné polia alebo mapy, ktoré iba rastú (história, cooldowny, cache výsledkov). | Mažte staré položky, alebo dáta ukladajte do databázy. |
setInterval alebo poslucháči udalostí pridávaní opakovane (napríklad v obsluhe príkazu). | Poslucháčov registrujte raz pri štarte. |
Obmedzenie 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.– obmedzí veľkosť cache;cacheWithLimits({ … }) MessageManager: 50= najviac 50 správ na kanál....Options.– ostatné cache ponechá v predvolenom nastavení.DefaultMakeCacheSettings sweepers.messages– každú hodinu (interval: 3_600sekúnd) zmaže z cache správy staršie než 30 minút (lifetime: 1_800).
Niektoré cache neobmedzujte
Dokumentácia discord.js varuje, že obmedzenie cache pre GuildManager, ChannelManager, GuildChannelManager, RoleManager a PermissionOverwriteManager nie je podporované a rozbije funkcie knižnice.
Ak bot po optimalizácii naozaj potrebuje viac pamäte, prejdite na väčší balík v záložke Zmena balíka. Doplatíte iba rozdiel do konca obdobia, postup je v článku Predĺženie a upgrade.
Bot na vlastnom VPS#
Ak bota prevádzkujete na VPS, nastavte ho ako službu systemd. Tá zaistí automatický reštart aj spustenie po reštarte VPS a logy uloží do systémového journalu (journalctl -u <NAZEV_SLUZBY> -f). Postup: Aplikácia 24/7 cez systemd.
Keď niečo nefunguje#
Error: Cannot find module 'discord.js'#
Nie sú nainštalované balíčky (chýba priečinok node_modules, alebo v ňom balíček nie je). Skontrolujte, že v koreni projektu je package.json a že má discord.js v časti dependencies. Ako sa balíčky u nás inštalujú, opisuje návod Nahranie a spustenie bota.
Error: Cannot find module '…/index.js' alebo './commands/ping.js'#
Node.js nenašiel súbor podľa cesty:
- Hlavný súbor má iný názov alebo je v podpriečinku, než očakáva nastavenie spustenia.
- Veľké a malé písmená: Windows ich nerozlišuje, server s Linuxom áno.
require(na serveri nenájde priečinok'. /Commands/ ping. js') commands. Zjednoťte názvy. - Relatívna cesta sa počíta od súboru, v ktorom je
require, nie od priečinka, z ktorého bot štartuje. Používajtepath.join(__dirname, …).
Error [ERR_REQUIRE_ESM]: require() of ES Module … not supported#
Načítavate príkazom require() balíček, ktorý existuje iba ako ES modul (napríklad novšie verzie niektorých knižníc). Riešenie:
- Prejdite v projekte na ES moduly (
import), pozri ďalšiu chybu. - Alebo načítajte balíček dynamicky:
const { default: knihovna } = await import('nazev-balicku');. - Alebo použite staršiu verziu balíčka, ktorá ešte podporuje CommonJS.
Novší Node.js (od verzie 20.19 a 22.12) vie require() ES modulov načítať a túto chybu hlási iba pri starších verziách. Pri moduloch s await na najvyššej úrovni hlási ERR_REQUIRE_ASYNC_MODULE. Ktorú verziu Node.js bot používa, zistíte podľa návodu Verzia Node.js.
ReferenceError: require is not defined in ES module scope, you can use import instead#
Projekt je nastavený ako ES moduly ("type": "module" v package.json, alebo súbor s príponou .mjs), ale kód používa require(). Buď prepíšte require na import (import { Client } from 'discord.js';), alebo z package.json odstráňte "type": "module". V ES moduloch tiež nefunguje __dirname; použite import.meta.dirname (Node.js 20.11 a novší).
SyntaxError: Cannot use import statement outside a module#
Opak predchádzajúcej chyby: kód používa import, ale projekt je CommonJS (typicky "type": "commonjs" v package.json). Do package.json pridajte "type": "module", alebo používajte require(). Kód v jednom projekte nemiešajte.
SyntaxError: Unexpected token (napríklad '?' alebo '.')#
Kód používa syntax, ktorú verzia Node.js na serveri ešte nepozná. Zistite verziu (console. na začiatku bota) a porovnajte ju s požiadavkami knižníc: discord.js 14 vyžaduje Node.js 18 alebo novší. Postup: Verzia Node.js.
Error: Used disallowed intents#
Bot žiada o privilegovaný intent, ktorý nemá v Discord Developer Portali zapnutý. Otvorte Developer Portal (otvorí sa v novom okne), svoju aplikáciu, sekciu Bot a v časti Privileged Gateway Intents zapnite to, čo bot naozaj používa (Presence Intent, Server Members Intent, Message Content Intent). Alebo intent z kódu odstráňte. Podrobne: Token a intenty.
An invalid token was provided. (TokenInvalid)#
Token je nesprávny, zneplatnený (po Reset Token v Developer Portali) alebo sa do bota vôbec nenačítal (premenná prostredia je prázdna, súbor .env chýba alebo sa nenačítava). Vypíšte si na kontrolu iba dĺžku tokenu, nikdy celý token: console.log('Délka tokenu:', process.. Názov premennej použite ten, ktorý máte v kóde. Postup: Token a intenty.
DiscordAPIError[50013]: Missing Permissions#
Bot nemá oprávnenie na akciu (poslať správu, pridať rolu, zmazať správu, zabanovať):
- Skontrolujte role bota v nastaveniach Discord servera a oprávnenia v danom kanáli (kanál môže práva prepísať).
- Poradie rolí: bot môže spravovať iba role, ktoré sú v zozname rolí pod jeho najvyššou rolou. Presuňte rolu bota vyššie.
- Vlastníka servera nemôže bot nijako upraviť.
DiscordAPIError[50001]: Missing Access#
Bot nevidí kanál alebo server: nemá v kanáli právo Zobraziť kanál, na serveri vôbec nie je, alebo registrujete príkazy pre server s nesprávnym ID (bot na ňom nie je). Ak bota niekto pozval iba s rozsahom bot pred dlhším časom a registrácia príkazov stále zlyháva, pozvite ho znova odkazom s rozsahmi bot a applications.commands.
DiscordAPIError[10062]: Unknown interaction#
Na interakciu (slash príkaz, tlačidlo) sa musí odpovedať do 3 sekúnd. Keď príkaz trvá dlhšie (databáza, API), zavolajte hneď na začiatku await interaction. a výsledok pošlite neskôr cez interaction.editReply(…). Odložená odpoveď platí 15 minút.
Rovnakú chybu (alebo DiscordAPIError[40060]: Interaction has already been acknowledged) spôsobia aj dve spustené kópie bota s rovnakým tokenom, napríklad u nás a zároveň vo vašom počítači. Obe sa snažia odpovedať. Nechajte bežať iba jednu.
ECONNRESET, ETIMEDOUT, EAI_AGAIN#
Dočasný výpadok siete alebo spojenia s Discordom. discord.js sa k bráne pripojí znova sám a neúspešné požiadavky REST API niekoľkokrát zopakuje. Ak sa chyba opakuje dlhodobo, pozrite sa na stav našich služieb a na stav Discordu (discordstatus.com (otvorí sa v novom okne)).
Bot je pomalý, vo výpise je 429 alebo rate limit#
Discord obmedzuje počet požiadaviek (globálne 50 za sekundu na bota a ďalšie limity pre jednotlivé akcie). discord.js pri prekročení automaticky počká a požiadavku pošle neskôr, preto bot „spomalí“. Neposielajte hromadne správy, role ani úpravy v slučke.
Opakované chybné požiadavky = blokovanie IP adresy
Keď bot pošle za 10 minút 10 000 neplatných požiadaviek (odpovede 401, 403 alebo 429), Discord IP adresu dočasne zablokuje. Typicky to spôsobí slučka, ktorá stále skúša akciu bez oprávnenia alebo s nesprávnym tokenom. Takú chybu opravte hneď, nie reštartom.
Bot je online, ale nereaguje na správy#
Na čítanie obsahu správ (messageCreate a message.content) potrebuje bot intenty GuildMessages a MessageContent v kóde a zapnutý Message Content Intent v Developer Portali. Bez neho je message.content prázdne. Pre príkazy radšej používajte slash príkazy, ktoré tento intent nepotrebujú (prvý bot v discord.js).
Bot je offline#
- Pozrite sa do záložky Konzola: beží bot, alebo je vypnutý? Vypnutého spustite tlačidlom Spustiť.
- Ak sa spustí a hneď spadne, prečítajte si prvú chybu vo výpise a nájdite ju vyššie.
- Ak beží bez chyby, ale je offline, skontrolujte token (resetovaný token = bot sa neprihlási).
Nič z toho nepomohlo: kedy napísať podpore#
Napíšte nám (kontakty), keď:
- sa konzola nenačíta alebo tlačidlá Spustiť a Reštartovať nereagujú,
- bot sa nedá spustiť ani s minimálnym kódom, ktorý inde funguje,
- potrebujete inú verziu Node.js alebo viac pamäte.
Pošlite názov alebo ID služby, čas problému a presné chybové hlásenie (skopírovaný text z konzoly). Nikdy neposielajte token bota.
Zhrnutie
- Výpis bota nájdete v záložke Konzola, pre históriu zapisujte aj do súboru.
- Po páde sa bot reštartuje sám; keď padá hneď po štarte, oprava je v kóde.
- Poslucháči
Events.Error,unhandledRejectionatry/catchv príkazoch zabránia pádu kvôli jednej chybe. Used disallowed intentsaTokenInvalidsa riešia v Developer Portali,Missing Permissionsv roliach na Discord serveri.Unknown interaction= neskorá odpoveď (použitedeferReply) alebo dve bežiace kópie bota.