Przejdź do treści
Aktualny kupon:10% zniżkiUżyj w zamówieniu

Bot Discord: logi, restarty i naprawianie błędów

Gdzie znaleźć wyjście bota, jak działa automatyczny restart, jak przechwytywać błędy, aby bot się nie zawieszał, i co oznaczają najczęstsze komunikaty, od Cannot find module po Missing Permissions.

  • początkujący
  • ~15 min
  • Zaktualizowano 9.10.2026

Gdy bot nie działa, odpowiedź prawie zawsze znajduje się w jego wyjściu. Pokażemy, gdzie je znaleźć, jak działa automatyczny restart, jak przechwytywać błędy w kodzie i co oznaczają najczęstsze komunikaty.

Czego potrzebujesz

  • Bot Discord w StormHost (lub na własnym VPS)
  • Dostęp do strefy klienta
  • Bot napisany w Node.js; przykłady kodu są dla discord.js w wersji 14
  • Około 15 minut

Gdzie znaleźć logi#

W strefie klienta otwórz Moje usługi, kliknij swojego bota i zostań w zakładce Konsola.

  • Konsola pokazuje na żywo wszystko, co bot wypisuje: console.log() i console.info() trafiają na standardowe wyjście, console.error() i console.warn() na wyjście błędów. Gdy aplikacja się zawiesi, zobaczysz tu jej wyjście (błąd z listą plików i linii, czyli stack trace).
  • Pod konsolą widzisz bieżące zużycie CPU, RAM, dysku i sieci.
  • Przyciski Start, Restart i Stop znajdują się w zakładce Konsola, nad samą konsolą.

Tryb streamera

Konsola bota ukrywa adresy IP w wyjściu tylko wtedy, gdy włączony jest tryb streamera. Nie ukryje jednak za Ciebie tokenu ani haseł. Nigdy nie wypisuj ich do konsoli i nigdy nie udostępniaj zrzutu ekranu, na którym są widoczne. Więcej w poradniku Strefa klienta.

Logowanie do pliku#

Konsola pokazuje tylko najnowszą część wyjścia. Jeśli chcesz sprawdzić, co działo się w nocy, zapisuj ważne zdarzenia także do pliku. Prosty pomocnik dla CommonJS (require):

logger.jsJavaScript
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),
};
CzęśćCo robi
fs.mkdirSync(slozka, { recursive: true })Tworzy folder logs obok pliku, jeśli nie istnieje.
createWriteStream(…, { flags: 'a' })Otwiera plik do dopisywania na końcu (a = append); stare wpisy zostają.
new Date().toISOString()Czas zdarzenia w UTC, na przykład 2026-10-01T18:04:12.345Z.
util.format(...casti)Łączy części komunikatu tak samo jak console.log. Dla błędu zapisuje też listę linii (stack trace), dla obiektu jego zawartość.
console.error / console.logLinia pojawia się także w konsoli.
soubor.write(radek + '\n')Zapisuje linię do logs/bot.log.

Użycie w bocie: const log = require('./logger');, a potem log.info('Bot gotowy') lub log.error('Polecenie nie powiodło się:', chyba). Plik logs/bot.log możesz pobrać w zakładce Pliki. Co jakiś czas go usuń lub opróżnij, aby nie zapełnił dysku.

Automatyczny restart#

Gdy bot się zawiesi (proces kończy się błędem), uruchamia się ponownie automatycznie. Krótkiej przerwy często nawet nie zauważysz, ale błąd zobaczysz w wyjściu konsoli.

  • Jeśli bot pada w kółko tuż po starcie, błąd jest w kodzie lub ustawieniach i restart go nie naprawi. Przeczytaj pierwszy błąd w wyjściu, popraw go i uruchom bota przyciskiem Start.
  • Nie używaj process.exit() w kodzie jako zwykłego sposobu zatrzymania bota. Bot ma działać bez przerwy.
  • Po przesłaniu nowego kodu lub zmianie zmiennych w zakładce Ustawienia użyj Restart; zmiany zaczynają obowiązywać dopiero po restarcie.

Przechwytywanie błędów, aby bot się nie zawieszał#

Node.js kończy proces przy każdym błędzie, którego nikt nie przechwyci. Dotyczy to także odrzuconego Promise bez catch (domyślne zachowanie od Node.js 15). Jeden błąd w jednym poleceniu może położyć całego bota. Dodaj do pliku głównego (na przykład index.js) te nasłuchiwacze:

index.jsJavaScript
const { Client, Events, GatewayIntentBits } = require('discord.js');

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.on(Events.Error, (chyba) => console.error('Błąd klienta discord.js:', chyba));
client.on(Events.Warn, (zprava) => console.warn('Ostrzeżenie discord.js:', zprava));
client.on(Events.ShardError, (chyba) => console.error('Błąd połączenia z Discordem:', chyba));

process.on('unhandledRejection', (duvod) => {
  console.error('Nieobsłużone odrzucenie promise:', duvod);
});

process.on('uncaughtException', (chyba) => {
  console.error('Nieprzechwycony wyjątek, bot zostanie zakończony:', chyba);
  process.exit(1);
});
NasłuchiwaczKiedy się uruchamiaPo co go dodać
Events.ErrorKlient discord.js zgłasza błąd.Bez nasłuchiwacza zdarzenie error kończy proces.
Events.WarnKlient zgłasza ostrzeżenie.Ostrzega o problemie, zanim coś się zawiesi.
Events.ShardErrorBłąd połączenia z gateway Discorda (websocket).discord.js łączy się ponownie sam; zobaczysz, dlaczego do tego doszło.
unhandledRejectionPromise zakończył się błędem i nikt go nie przechwycił (brak await wewnątrz try albo brak .catch()).Bot nie zawiesi się przez jeden zapomniany błąd, a Ty zobaczysz, skąd pochodzi.
uncaughtExceptionSynchroniczny błąd, którego nic nie przechwyciło.Wypisuje błąd i kończy bota. Po takim błędzie kontynuowanie nie jest bezpieczne; automatyczny restart uruchomi bota ponownie w czystym stanie.

Błędy w poszczególnych poleceniach przechwytuj bezpośrednio w obsłudze interakcji, aby użytkownik dostał odpowiedź, a bot działał dalej:

JavaScript
const { Events, MessageFlags } = require('discord.js');

client.on(Events.InteractionCreate, async (interaction) => {
  if (!interaction.isChatInputCommand()) return;

  try {
    await zpracujPrikaz(interaction);
  } catch (chyba) {
    console.error(`Polecenie /${interaction.commandName} nie powiodło się:`, chyba);
    const odpoved = { content: 'Podczas wykonywania tego polecenia wystąpił błąd.', flags: MessageFlags.Ephemeral };
    if (interaction.replied || interaction.deferred) {
      await interaction.followUp(odpoved).catch(console.error);
    } else {
      await interaction.reply(odpoved).catch(console.error);
    }
  }
});
  • isChatInputCommand() – obsługuje tylko polecenia slash.
  • zpracujPrikaz(interaction) – Twoja funkcja z logiką polecenia.
  • try { … } catch (chyba) { … } – błąd w poleceniu trafia do catch zamiast zawieszać bota.
  • MessageFlags.Ephemeral – odpowiedź widzi tylko użytkownik, który uruchomił polecenie.
  • interaction.replied || interaction.deferred – jeśli bot już odpowiedział lub odroczył odpowiedź, kolejną wiadomość musi wysłać przez followUp, w przeciwnym razie przez reply.
  • .catch(console.error) – jeśli nawet odpowiedź o błędzie się nie powiedzie, zostanie tylko wypisana.

Pamięć#

Bot ma tyle RAM, ile zapewnia pakiet. Gdy jej zabraknie, zawiesza się (i restartuje automatycznie) albo znacznie zwalnia. Typowy komunikat przy awarii:

Wyniktext
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

Ten komunikat wypisuje sam Node.js, gdy zabraknie mu pamięci na obiekty JavaScript. Gdy proces zabija system z powodu limitu pamięci, wyjście może urwać się bez żadnego komunikatu o błędzie. W obu przypadkach warto sprawdzić, co zużywa pamięć (zobacz niżej).

Obserwuj zużycie pod konsolą albo niech bot sam je wypisuje:

JavaScript
setInterval(() => {
  const mb = (b) => Math.round(b / 1024 / 1024);
  const m = process.memoryUsage();
  console.log(`Pamięć: łącznie ${mb(m.rss)} MB, sterta ${mb(m.heapUsed)}/${mb(m.heapTotal)} MB`);
}, 10 * 60 * 1000);
  • process.memoryUsage() – bieżące zużycie procesu; rss to pamięć łącznie, heapUsed pamięć zajęta przez obiekty JavaScript.
  • 10 * 60 * 1000 – wypisuje co 10 minut (wartość w milisekundach).

Jeśli pamięć stale rośnie, najczęstsze przyczyny to:

PrzyczynaRozwiązanie
discord.js trzyma w pamięci wiadomości, członków i inne obiekty (cache). Na dużych serwerach to dziesiątki tysięcy elementów.Ogranicz cache i pozwól na usuwanie starych elementów (przykład niżej). Nie włączaj intentu GuildMembers, jeśli go nie potrzebujesz, i nie pobieraj wszystkich członków (guild.members.fetch()) bez powodu.
Własne tablice lub mapy, które tylko rosną (historia, cooldowny, buforowane wyniki).Usuwaj stare elementy albo przechowuj dane w bazie danych.
setInterval lub nasłuchiwacze zdarzeń dodawane w kółko (na przykład wewnątrz obsługi polecenia).Rejestruj nasłuchiwacze raz, przy starcie.

Ograniczanie cache w discord.js:

JavaScript
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.cacheWithLimits({ … }) – ogranicza rozmiar cache; MessageManager: 50 = maksymalnie 50 wiadomości na kanał.
  • ...Options.DefaultMakeCacheSettings – pozostałe cache zostają z ustawieniami domyślnymi.
  • sweepers.messages – co godzinę (interval: 3_600 sekund) usuwa z cache wiadomości starsze niż 30 minut (lifetime: 1_800).

Niektórych cache nie ograniczaj

Dokumentacja discord.js ostrzega, że ograniczanie cache dla GuildManager, ChannelManager, GuildChannelManager, RoleManager i PermissionOverwriteManager nie jest wspierane i psuje funkcje biblioteki.

Jeśli po optymalizacji bot naprawdę potrzebuje więcej pamięci, przejdź na większy pakiet w zakładce Zmiana pakietu. Do końca okresu płacisz tylko różnicę; kroki znajdziesz w artykule Przedłużenie i upgrade.

Bot na własnym VPS#

Jeśli uruchamiasz bota na VPS, skonfiguruj go jako usługę systemd. Zyskasz automatyczne restarty i uruchamianie po restarcie VPS, a logi trafią do dziennika systemowego (journalctl -u <NAZWA_USLUGI> -f). Kroki: Aplikacja działająca 24/7 z systemd.

Rozwiązywanie problemów#

Error: Cannot find module 'discord.js'#

Pakiety nie są zainstalowane (brakuje folderu node_modules albo nie ma w nim pakietu). Sprawdź, czy w katalogu głównym projektu jest package.json z discord.js w dependencies. Jak instalowane są pakiety na naszych serwerach, opisuje poradnik Przesyłanie i uruchomienie bota.

Error: Cannot find module '…/index.js' lub './commands/ping.js'#

Node.js nie znalazł pliku pod tą ścieżką:

  • Plik główny ma inną nazwę albo leży w innym podfolderze, niż oczekują ustawienia uruchamiania.
  • Wielkość liter: Windows jej nie rozróżnia, ale serwer Linux tak. require('./Commands/ping.js') nie znajdzie na serwerze folderu commands. Ujednolić nazwy.
  • Ścieżka względna jest liczona od pliku zawierającego require, a nie od folderu, w którym bot startuje. Użyj path.join(__dirname, …).

Error [ERR_REQUIRE_ESM]: require() of ES Module … not supported#

Wczytujesz przez require() pakiet, który istnieje tylko jako moduł ES (na przykład nowsze wersje niektórych bibliotek). Rozwiązania:

  • Przełącz projekt na moduły ES (import), zobacz następny błąd.
  • Albo wczytaj pakiet dynamicznie: const { default: library } = await import('nazwa-pakietu');.
  • Albo użyj starszej wersji pakietu, która nadal wspiera CommonJS.

Nowsze wersje Node.js (20.19 i 22.12 oraz nowsze) potrafią wczytywać moduły ES przez require() i zgłaszają ten błąd tylko w starszych wersjach. Dla modułów z await na najwyższym poziomie zgłaszają ERR_REQUIRE_ASYNC_MODULE. Jak sprawdzić, której wersji Node.js używa Twój bot, opisuje sekcja Wersja Node.js.

ReferenceError: require is not defined in ES module scope, you can use import instead#

Projekt jest skonfigurowany jako moduły ES ("type": "module" w package.json albo plik z rozszerzeniem .mjs), ale kod używa require(). Albo przepisz require na import (import { Client } from 'discord.js';), albo usuń "type": "module" z package.json. W modułach ES nie działa też __dirname; użyj import.meta.dirname (Node.js 20.11 i nowsze).

SyntaxError: Cannot use import statement outside a module#

Odwrotność poprzedniego błędu: kod używa import, ale projekt jest CommonJS (zazwyczaj "type": "commonjs" w package.json). Dodaj "type": "module" do package.json albo użyj require(). Nie mieszaj obu w jednym projekcie.

SyntaxError: Unexpected token (na przykład '?' lub '.')#

Kod używa składni, której wersja Node.js na serwerze jeszcze nie wspiera. Sprawdź wersję (console.log(process.version) na początku bota) i porównaj ją z wymaganiami swoich bibliotek: discord.js 14 wymaga Node.js 18 lub nowszego. Kroki: Wersja Node.js.

Error: Used disallowed intents#

Bot żąda uprzywilejowanego intentu, który nie jest włączony w Discord Developer Portal. Otwórz Developer Portal (otwiera się w nowym oknie), swoją aplikację i sekcję Bot, a w Privileged Gateway Intents włącz to, czego bot faktycznie używa (Presence Intent, Server Members Intent, Message Content Intent). Albo usuń intent z kodu. Szczegóły: Token i intenty.

An invalid token was provided. (TokenInvalid)#

Token jest błędny, został unieważniony (po Reset Token w Developer Portal) albo nigdy nie został wczytany do bota (zmienna środowiskowa jest pusta, brakuje pliku .env albo nie jest wczytywany). Aby to sprawdzić, wypisz tylko długość tokenu, nigdy cały token: console.log('Długość tokenu:', process.env.DISCORD_TOKEN?.length);. Użyj nazwy zmiennej, którą masz w kodzie. Kroki: Token i intenty.

DiscordAPIError[50013]: Missing Permissions#

Bot nie ma uprawnienia do danej akcji (wysłanie wiadomości, dodanie roli, usunięcie wiadomości, ban):

  • Sprawdź role bota w ustawieniach serwera Discord oraz uprawnienia na tym kanale (kanał może nadpisywać uprawnienia).
  • Kolejność ról: bot może zarządzać tylko rolami, które na liście ról są poniżej jego najwyższej roli. Przeciągnij rolę bota wyżej.
  • Bot w żaden sposób nie może modyfikować właściciela serwera.

DiscordAPIError[50001]: Missing Access#

Bot nie widzi kanału lub serwera: nie ma na kanale uprawnienia Wyświetlanie kanału, w ogóle nie ma go na serwerze albo rejestrujesz polecenia dla serwera o błędnym ID (bota na nim nie ma). Jeśli ktoś dawno temu zaprosił bota tylko ze scope bot, a rejestracja poleceń wciąż się nie udaje, zaproś go ponownie linkiem ze scopes bot i applications.commands.

DiscordAPIError[10062]: Unknown interaction#

Na interakcję (polecenie slash, przycisk) trzeba odpowiedzieć w ciągu 3 sekund. Gdy polecenie trwa dłużej (baza danych, API), na samym początku wywołaj await interaction.deferReply();, a wynik wyślij później przez interaction.editReply(…). Odroczona odpowiedź pozostaje ważna przez 15 minut.

Ten sam błąd (albo DiscordAPIError[40060]: Interaction has already been acknowledged) pojawia się także wtedy, gdy działają dwie kopie bota z tym samym tokenem, na przykład jedna na naszych serwerach, a druga na Twoim komputerze. Obie próbują odpowiedzieć. Zostaw uruchomioną tylko jedną.

ECONNRESET, ETIMEDOUT, EAI_AGAIN#

Chwilowa awaria sieci albo zerwane połączenie z Discordem. discord.js sam łączy się ponownie z gateway i kilkakrotnie ponawia nieudane żądania REST API. Jeśli błąd powraca przez dłuższy czas, sprawdź nasz status usług i status Discorda (discordstatus.com (otwiera się w nowym oknie)).

Bot jest wolny, a w wyjściu pojawia się 429 lub rate limit#

Discord ogranicza liczbę żądań (globalnie 50 na sekundę na bota, plus inne limity dla poszczególnych akcji). Po przekroczeniu limitu discord.js automatycznie czeka i wysyła żądanie później, dlatego bot „zwalnia”. Nie wysyłaj wiadomości, ról ani edycji hurtowo w pętli.

Powtarzające się błędne żądania = blokada adresu IP

Gdy bot wyśle 10 000 błędnych żądań w ciągu 10 minut (odpowiedzi 401, 403 lub 429), Discord tymczasowo blokuje adres IP. Zazwyczaj powoduje to pętla, która w kółko próbuje wykonać akcję bez uprawnień albo z błędnym tokenem. Taki błąd napraw od razu, nie restartem.

Bot jest online, ale nie reaguje na wiadomości#

Aby czytać treść wiadomości (messageCreate i message.content), bot potrzebuje w kodzie intentów GuildMessages i MessageContent oraz włączonego Message Content Intent w Developer Portal. Bez niego message.content jest puste. Do poleceń używaj zamiast tego poleceń slash, które nie potrzebują tego intentu (pierwszy bot discord.js).

Bot jest offline#

  1. Spójrz na zakładkę Konsola: bot działa czy jest zatrzymany? Jeśli jest zatrzymany, uruchom go przyciskiem Start.
  2. Jeśli startuje i od razu pada, przeczytaj pierwszy błąd w wyjściu i odszukaj go wyżej.
  3. Jeśli działa bez błędów, ale jest offline, sprawdź token (po zresetowaniu tokenu stary przestaje działać i bot nie może się zalogować).

Nic nie pomogło: kiedy skontaktować się z pomocą techniczną#

Skontaktuj się z nami (kontakt), gdy:

  • konsola się nie ładuje albo przyciski Start i Restart nie reagują,
  • bot nie uruchamia się nawet z minimalnym kodem, który działa gdzie indziej,
  • potrzebujesz innej wersji Node.js lub więcej pamięci.

Prześlij nam nazwę lub ID usługi, czas wystąpienia problemu i dokładny komunikat błędu (tekst skopiowany z konsoli). Nigdy nie wysyłaj tokenu bota.

Podsumowanie

  • Wyjście bota znajdziesz w zakładce Konsola; dla historii zapisuj je także do pliku.
  • Bot po awarii restartuje się sam; jeśli pada tuż po starcie, poprawka jest w kodzie.
  • Nasłuchiwacze Events.Error i unhandledRejection oraz try/catch w poleceniach chronią bota przed zawieszeniem przez jeden błąd.
  • Used disallowed intents i TokenInvalid naprawisz w Developer Portal, Missing Permissions w rolach na serwerze Discord.
  • Unknown interaction = spóźniona odpowiedź (użyj deferReply) albo dwie działające kopie bota.

Wyszukiwanie w poradnikach