Naar de inhoud
Actuele kortingscode:10% kortingGebruiken bij je bestelling

Discord-bot: logs, herstart en fouten oplossen

Waar je de uitvoer van je bot vindt, hoe de automatische herstart werkt, hoe je fouten afvangt zodat de bot niet crasht en wat de meest voorkomende meldingen betekenen, van Cannot find module tot Missing Permissions.

  • beginner
  • ~15 min
  • Bijgewerkt op 2-10-2026

Als je bot niet werkt, staat het antwoord bijna altijd in zijn uitvoer. We laten zien waar je de uitvoer vindt, hoe de automatische herstart werkt, hoe je fouten in de code afvangt en wat de meest voorkomende meldingen betekenen.

Wat je nodig hebt

  • Een Discord-bot bij StormHost (of op je eigen VPS)
  • Toegang tot je klantaccount
  • Een bot die in Node.js is geschreven; de codevoorbeelden zijn voor discord.js versie 14
  • Ongeveer 15 minuten

Waar je de logs vindt#

Open in je klantaccount Mijn diensten, klik op de bot en blijf op het tabblad Console.

  • De console toont live alles wat de bot uitvoert: console.log() en console.info() naar de standaarduitvoer, console.error() en console.warn() naar de foutuitvoer. De uitvoer van een crashende applicatie (een fout met een lijst van bestanden en regels, de zogeheten stack trace) zie je hier.
  • Onder de console zie je het actuele gebruik van CPU, RAM, schijf en netwerk.
  • De knoppen Starten, Herstarten en Stoppen staan op het tabblad Console, boven de console zelf.

Streamermodus

De console van de bot verbergt IP-adressen in de uitvoer alleen als de streamermodus aanstaat. Je token en wachtwoorden verbergt hij echter niet voor je. Schrijf ze nooit naar de console en deel geen schermafbeelding waarop ze te zien zijn. Meer in de handleiding Klantaccount.

Loggen naar een bestand#

De console toont alleen het laatste deel van de uitvoer. Wil je kunnen nagaan wat er gisternacht is gebeurd, schrijf belangrijke gebeurtenissen dan ook naar een bestand. Een eenvoudige helper voor 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),
};
OnderdeelWat het doet
fs.mkdirSync(slozka, { recursive: true })Maakt de map logs naast het bestand aan als die nog niet bestaat.
createWriteStream(…, { flags: 'a' })Opent het bestand om aan het einde bij te schrijven (a = append), oude regels blijven staan.
new Date().toISOString()Het tijdstip van de gebeurtenis in UTC, bijvoorbeeld 2026-10-01T18:04:12.345Z.
util.format(...casti)Voegt de delen van het bericht samen zoals console.log dat doet. Bij een fout schrijft het ook de lijst met regels (stack trace), bij een object de inhoud ervan.
console.error / console.logDe regel verschijnt tegelijk in de console.
soubor.write(radek + '\n')Schrijft de regel naar logs/bot.log.

Gebruik in de bot: const log = require('./logger'); en daarna log.info('Bot is klaar') of log.error('Commando mislukt:', chyba). Het bestand logs/bot.log download je op het tabblad Bestanden. Verwijder het af en toe of maak het leeg, zodat de schijf niet volloopt.

Automatische herstart#

Als de bot crasht (het proces eindigt met een fout), start hij automatisch opnieuw. Een korte storing merk je daardoor vaak niet eens, maar in de uitvoer van de console zie je de fout wel.

  • Als de bot direct na het starten steeds opnieuw crasht, zit de fout in de code of in de instellingen en lost een herstart die niet op. Lees de eerste fout in de uitvoer, los die op en start de bot met de knop Starten.
  • Gebruik process.exit() in je code niet als gewone manier om de bot te beëindigen. De bot hoort onafgebroken te draaien.
  • Gebruik Herstarten nadat je nieuwe code hebt geüpload of variabelen hebt gewijzigd op het tabblad Instellingen: de wijzigingen gaan pas in na een herstart.

Fouten afvangen zodat de bot niet crasht#

Node.js beëindigt het proces bij elke fout die niemand afvangt. Daar hoort ook een afgewezen Promise zonder catch bij (het standaardgedrag sinds Node.js 15). Eén fout in één commando kan zo de hele bot laten crashen. Voeg deze listeners toe aan het hoofdbestand (bijvoorbeeld index.js):

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

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

client.on(Events.Error, (chyba) => console.error('Fout in de discord.js-client:', chyba));
client.on(Events.Warn, (zprava) => console.warn('Waarschuwing van discord.js:', zprava));
client.on(Events.ShardError, (chyba) => console.error('Fout in de verbinding met Discord:', chyba));

process.on('unhandledRejection', (duvod) => {
  console.error('Niet-afgevangen fout in een Promise:', duvod);
});

process.on('uncaughtException', (chyba) => {
  console.error('Niet-afgevangen uitzondering, de bot wordt beëindigd:', chyba);
  process.exit(1);
});
ListenerWanneer hij wordt uitgevoerdWaarom je hem wilt hebben
Events.ErrorDe discord.js-client meldt een fout.Zonder listener beëindigt het event error het proces.
Events.WarnDe client meldt een waarschuwing.Wijst je op een probleem voordat er iets crasht.
Events.ShardErrorEen fout in de verbinding met de gateway van Discord (websocket).discord.js maakt zelf opnieuw verbinding, jij ziet waarom.
unhandledRejectionEen Promise is met een fout geëindigd en niemand heeft die afgevangen (er ontbreekt een await in een try of een .catch()).De bot crasht niet door één vergeten fout en je ziet waar die is ontstaan.
uncaughtExceptionEen synchrone fout die door niets is afgevangen.Toont de fout en beëindigt de bot. Na zo'n fout is het niet veilig om door te gaan, de automatische herstart start hem opnieuw in een schone toestand.

Vang fouten in afzonderlijke commando's direct af in de afhandeling van interacties, zodat de gebruiker een antwoord krijgt en de bot blijft draaien:

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(`Commando /${interaction.commandName} is mislukt:`, chyba);
    const odpoved = { content: 'Er is een fout opgetreden bij het uitvoeren van het commando.', flags: MessageFlags.Ephemeral };
    if (interaction.replied || interaction.deferred) {
      await interaction.followUp(odpoved).catch(console.error);
    } else {
      await interaction.reply(odpoved).catch(console.error);
    }
  }
});
  • isChatInputCommand() – verwerkt alleen slash-commando's.
  • zpracujPrikaz(interaction) – jouw functie met de logica van het commando.
  • try { … } catch (chyba) { … } – een fout in het commando eindigt in catch, niet in een crash van de bot.
  • MessageFlags.Ephemeral – het antwoord is alleen zichtbaar voor de gebruiker die het commando heeft gegeven.
  • interaction.replied || interaction.deferred – als de bot al heeft geantwoord of het antwoord heeft uitgesteld, moet hij het volgende bericht via followUp sturen, anders via reply.
  • .catch(console.error) – mocht ook het foutantwoord mislukken, dan wordt dat alleen naar de console geschreven.

Geheugen#

De bot heeft zoveel RAM tot zijn beschikking als je pakket biedt. Als hij dat opgebruikt, crasht hij (en herstart hij automatisch) of wordt hij merkbaar trager. Een typische melding bij een crash:

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

Deze melding komt van Node.js zelf, wanneer het geheugen voor JavaScript-objecten op is. Als het systeem het proces beëindigt vanwege de geheugenlimiet, kan de uitvoer ook zonder foutmelding eindigen. In beide gevallen helpt het om uit te zoeken wat het geheugen in beslag neemt (hieronder).

Houd het gebruik in de gaten onder de console, of laat de bot het naar de console schrijven:

JavaScript
setInterval(() => {
  const mb = (b) => Math.round(b / 1024 / 1024);
  const m = process.memoryUsage();
  console.log(`Geheugen: totaal ${mb(m.rss)} MB, heap ${mb(m.heapUsed)}/${mb(m.heapTotal)} MB`);
}, 10 * 60 * 1000);
  • process.memoryUsage() – het actuele gebruik van het proces; rss is het totale geheugen, heapUsed het geheugen van JavaScript-objecten.
  • 10 * 60 * 1000 – uitvoer om de 10 minuten (de waarde is in milliseconden).

Als het geheugengebruik blijft groeien, zijn dit de meest voorkomende oorzaken:

OorzaakOplossing
discord.js houdt berichten, leden en andere objecten in het geheugen (cache). Bij grote servers zijn dat tienduizenden items.Beperk de cache en laat oude items verwijderen (voorbeeld hieronder). Schakel de intent GuildMembers niet in als je hem niet nodig hebt en haal niet zonder reden alle leden op (guild.members.fetch()).
Eigen arrays of maps die alleen maar groeien (geschiedenis, cooldowns, cache met resultaten).Verwijder oude items of sla de gegevens op in een database.
setInterval of event-listeners die herhaaldelijk worden toegevoegd (bijvoorbeeld in de afhandeling van een commando).Registreer listeners één keer bij het starten.

De cache beperken in 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({ … }) – beperkt de grootte van de cache; MessageManager: 50 = hoogstens 50 berichten per kanaal.
  • ...Options.DefaultMakeCacheSettings – laat de overige caches op de standaardinstelling staan.
  • sweepers.messages – verwijdert elk uur (interval: 3_600 seconden) berichten ouder dan 30 minuten (lifetime: 1_800) uit de cache.

Beperk sommige caches niet

De documentatie van discord.js waarschuwt dat het beperken van de cache voor GuildManager, ChannelManager, GuildChannelManager, RoleManager en PermissionOverwriteManager niet wordt ondersteund en functies van de bibliotheek kapotmaakt.

Heeft de bot na het optimaliseren echt meer geheugen nodig, stap dan over op een groter pakket op het tabblad Pakket wijzigen. Je betaalt alleen het verschil tot het einde van de periode bij, de stappen staan in het artikel Verlenging en upgrade.

Bot op je eigen VPS#

Draai je de bot op een VPS, stel hem dan in als systemd-service. Die zorgt voor de automatische herstart en voor het starten na een herstart van de VPS, en slaat de logs op in het systeemjournaal (journalctl -u <SERVICENAAM> -f). Stappen: Applicatie 24/7 via systemd.

Als iets niet werkt#

Error: Cannot find module 'discord.js'#

De pakketten zijn niet geïnstalleerd (de map node_modules ontbreekt, of het pakket staat er niet in). Controleer of er in de hoofdmap van het project een package.json staat en of discord.js daarin onder dependencies staat. Hoe pakketten bij ons worden geïnstalleerd, lees je in de handleiding De bot uploaden en starten.

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

Node.js heeft het bestand op dat pad niet gevonden:

  • Het hoofdbestand heeft een andere naam of staat in een andere submap dan de startinstellingen verwachten.
  • Hoofdletters en kleine letters: Windows maakt er geen onderscheid tussen, een server met Linux wel. require('./Commands/ping.js') vindt op de server de map commands niet. Maak de namen gelijk.
  • Een relatief pad wordt berekend vanaf het bestand waarin de require staat, niet vanaf de map van waaruit de bot start. Gebruik path.join(__dirname, …).

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

Je laadt met require() een pakket dat alleen als ES-module bestaat (bijvoorbeeld nieuwere versies van sommige bibliotheken). Oplossingen:

  • Stap in het project over op ES-modules (import), zie de volgende fout.
  • Of laad het pakket dynamisch: const { default: bibliotheek } = await import('pakketnaam');.
  • Of gebruik een oudere versie van het pakket die CommonJS nog ondersteunt.

Nieuwere Node.js-versies (vanaf 20.19 en 22.12) kunnen ES-modules met require() laden en melden deze fout alleen bij oudere versies. Bij modules met await op het hoogste niveau melden ze ERR_REQUIRE_ASYNC_MODULE. Welke Node.js-versie de bot gebruikt, vind je met de handleiding Node.js-versie.

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

Het project is ingesteld als ES-modules ("type": "module" in package.json, of een bestand met de extensie .mjs), maar de code gebruikt require(). Herschrijf require naar import (import { Client } from 'discord.js';) of verwijder "type": "module" uit package.json. In ES-modules werkt ook __dirname niet; gebruik import.meta.dirname (Node.js 20.11 en nieuwer).

SyntaxError: Cannot use import statement outside a module#

Het omgekeerde van de vorige fout: de code gebruikt import, maar het project is CommonJS (meestal "type": "commonjs" in package.json). Voeg "type": "module" toe aan package.json of gebruik require(). Gebruik de twee niet door elkaar in één project.

SyntaxError: Unexpected token (bijvoorbeeld '?' of '.')#

De code gebruikt syntaxis die de Node.js-versie op de server nog niet kent. Zoek de versie op (console.log(process.version) aan het begin van de bot) en vergelijk die met de vereisten van de bibliotheken: discord.js 14 vereist Node.js 18 of nieuwer. Stappen: Node.js-versie.

Error: Used disallowed intents#

De bot vraagt om een geprivilegieerde intent die in het Discord Developer Portal niet is ingeschakeld. Open het Developer Portal (opent in een nieuw venster), je applicatie en de sectie Bot, en schakel onder Privileged Gateway Intents in wat de bot echt gebruikt (Presence Intent, Server Members Intent, Message Content Intent). Of verwijder de intent uit de code. Meer details: Token en intents.

An invalid token was provided. (TokenInvalid)#

Het token is onjuist, ongeldig gemaakt (na Reset Token in het Developer Portal) of helemaal niet in de bot geladen (de omgevingsvariabele is leeg, het bestand .env ontbreekt of wordt niet geladen). Toon ter controle alleen de lengte van het token, nooit het hele token: console.log('Lengte van het token:', process.env.DISCORD_TOKEN?.length);. Gebruik de naam van de variabele die je in je code hebt. Stappen: Token en intents.

DiscordAPIError[50013]: Missing Permissions#

De bot heeft geen rechten voor de actie (een bericht sturen, een rol toevoegen, een bericht verwijderen, iemand bannen):

  • Controleer de rollen van de bot in de instellingen van de Discord-server en de rechten in het betreffende kanaal (een kanaal kan rechten overschrijven).
  • Volgorde van rollen: de bot kan alleen rollen beheren die in de rollenlijst onder zijn hoogste rol staan. Sleep de rol van de bot hoger.
  • De bot kan de eigenaar van de server op geen enkele manier aanpassen.

DiscordAPIError[50001]: Missing Access#

De bot ziet het kanaal of de server niet: hij heeft in het kanaal niet het recht Kanaal weergeven, zit helemaal niet op de server, of je registreert commando's voor een server met het verkeerde ID (de bot zit er niet op). Als iemand de bot lang geleden alleen met de scope bot heeft uitgenodigd en het registreren van commando's blijft mislukken, nodig hem dan opnieuw uit met een link met de scopes bot en applications.commands.

DiscordAPIError[10062]: Unknown interaction#

Op een interactie (slash-commando, knop) moet binnen 3 seconden worden geantwoord. Duurt een commando langer (database, API), roep dan direct aan het begin await interaction.deferReply(); aan en stuur het resultaat later via interaction.editReply(…). Een uitgesteld antwoord is 15 minuten geldig.

Dezelfde fout (of DiscordAPIError[40060]: Interaction has already been acknowledged) ontstaat ook door twee draaiende kopieën van de bot met hetzelfde token, bijvoorbeeld bij ons en tegelijk op je eigen computer. Beide proberen te antwoorden. Laat er maar één draaien.

ECONNRESET, ETIMEDOUT, EAI_AGAIN#

Een tijdelijke storing van het netwerk of van de verbinding met Discord. discord.js maakt zelf opnieuw verbinding met de gateway en herhaalt mislukte verzoeken aan de REST API een paar keer. Blijft de fout lange tijd terugkomen, bekijk dan de status van onze diensten en de status van Discord (discordstatus.com (opent in een nieuw venster)).

De bot is traag, in de uitvoer staat 429 of rate limit#

Discord beperkt het aantal verzoeken (globaal 50 per seconde per bot en daarnaast limieten voor afzonderlijke acties). Bij overschrijding wacht discord.js automatisch en stuurt het verzoek later, daardoor wordt de bot “trager”. Verstuur geen berichten, rollen of wijzigingen in bulk in een lus.

Herhaalde ongeldige verzoeken = blokkade van het IP-adres

Als een bot in 10 minuten 10.000 ongeldige verzoeken stuurt (antwoorden 401, 403 of 429), blokkeert Discord het IP-adres tijdelijk. Meestal komt dat door een lus die steeds een actie probeert zonder rechten of met een verkeerd token. Los zo'n fout meteen op, niet met een herstart.

De bot is online, maar reageert niet op berichten#

Om de inhoud van berichten te lezen (messageCreate en message.content) heeft de bot de intents GuildMessages en MessageContent in de code nodig en moet Message Content Intent in het Developer Portal zijn ingeschakeld. Zonder die intent is message.content leeg. Gebruik voor commando's liever slash-commando's, die deze intent niet nodig hebben (eerste bot in discord.js).

De bot is offline#

  1. Kijk op het tabblad Console: draait de bot of is hij gestopt? Start een gestopte bot met de knop Starten.
  2. Als hij start en meteen crasht, lees dan de eerste fout in de uitvoer en zoek die hierboven op.
  3. Als hij zonder fouten draait maar offline is, controleer dan het token (gereset token = de bot logt niet in).

Niets hiervan heeft geholpen: wanneer je contact opneemt met support#

Stuur ons een bericht (contactgegevens) als:

  • de console niet laadt of de knoppen Starten en Herstarten niet reageren,
  • de bot zelfs niet start met minimale code die elders wel werkt,
  • je een andere Node.js-versie of meer geheugen nodig hebt.

Stuur de naam of het ID van de dienst, het tijdstip van het probleem en de exacte foutmelding (gekopieerde tekst uit de console). Stuur nooit het token van de bot.

Samenvatting

  • De uitvoer van de bot vind je op het tabblad Console, schrijf voor de geschiedenis ook naar een bestand.
  • Na een crash herstart de bot vanzelf; crasht hij direct na het starten, dan zit de oplossing in de code.
  • De listeners Events.Error en unhandledRejection en try/catch in commando's voorkomen een crash door één fout.
  • Used disallowed intents en TokenInvalid los je op in het Developer Portal, Missing Permissions in de rollen op de Discord-server.
  • Unknown interaction = een te laat antwoord (gebruik deferReply) of twee draaiende kopieën van de bot.

Zoeken in de handleidingen