#4122·mineflayer

kicked event's reason is typed as string but can be a raw chat-component object

Author: DallasCarraherCreated Sep 15, 2026Updated Sep 15, 2026

Description

lib/plugins/kick.js forwards packet.reason straight from the kick_disconnect/disconnect packets:

javascript
bot._client.on('kick_disconnect', (packet) => {
  bot.emit('kicked', packet.reason, true)
})
bot._client.on('disconnect', (packet) => {
  bot.emit('kicked', packet.reason, false)
})

index.d.ts declares this as kicked: (reason: string, loggedIn: boolean) => ..., but on modern protocol versions packet.reason is decoded as a JSON chat-component object (e.g. { translate: 'disconnect.timeout' }), not a string. Anything that does `kicked: ${reason}` or otherwise treats it as a string gets "[object Object]" instead of the actual kick message.

To Reproduce

Get kicked/disconnected from a server on a recent protocol version (I hit this on 1.21-era realms via [email protected]) and log the kicked event's reason argument — it logs as an object, and any string coercion of it collapses to [object Object].

Expected behavior

reason should either genuinely be a string (matching the documented type), or the type should be corrected and docs updated to reflect that consumers need to parse/render it themselves.

Suggested fix

Happy to send a PR. lib/plugins/chat.js already has the right pattern for this (require('prismarine-chat')(bot.registry) → render to a string), so kick.js could do the same before emitting, making reason actually match its declared string type. Only question is whether that's the preferred direction vs. just fixing the type declaration and leaving the raw value as-is — wanted to check before opening a PR in case there's a preference (e.g. backwards-compat concerns for anyone currently branching on the object shape).

Versions

  • mineflayer: 4.39.0
  • node: (n/a — reproduced via a Bun app, but the bug is in kick.js/index.d.ts, not runtime-specific)