Objetivos de aprendizaje
Después de leer este artículo podrás:
- Distinguir un bot de prefijo (mensajes) de un bot de slash commands (interacciones)
- Diagnosticar intents, registro de comandos, permisos y el plazo de 3 segundos
- Corregir cada causa con código actual de discord.js v14
En esta página
- ¿Cómo saber si el bot recibe el evento?
- ¿Por qué el bot de prefijo ignora los mensajes?
- ¿Por qué el slash command no aparece o no hace nada?
- ¿Por qué aparece "La aplicación no ha respondido"?
- ¿El bot tiene permiso para responder en ese canal?
- ¿Y si el handler falla en silencio?
- Cómo hacerlo en Square Cloud
- Preguntas frecuentes
El bot tiene el punto verde, pero escribes el comando y no pasa nada. Eso es distinto de un bot desconectado: aquí la conexión con el Gateway existe, y el problema está en lo que el bot recibe, en lo que tiene permitido hacer o en lo que tarda en responder.
Una pregunta decide todo el diagnóstico: ¿tu comando es un mensaje con prefijo (!ping) o un slash command (/ping)? Los dos usan eventos distintos y fallan por motivos distintos.
¿Cómo saber si el bot recibe el evento?#
Antes de sospechar de intents o permisos, demuestra que el evento llega. Un console.log en la primera línea del handler separa "el bot ni lo recibe" de "lo recibe y falla después".
import { Client, Events, GatewayIntentBits } from "discord.js";
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});
client.on(Events.MessageCreate, (m) => console.log("msg:", JSON.stringify(m.content)));
client.on(Events.InteractionCreate, (i) => console.log("interaction:", i.type, i.commandName));
client.login(process.env.DISCORD_TOKEN);Si msg: aparece con "" (vacío) en mensajes que sí tienen texto, la causa es la intent de contenido. Si no aparece nada con el slash command, el problema es el registro o el scope. Si aparece y el usuario no ve respuesta, el problema es de permisos, un error en el handler o el tiempo.
¿Por qué el bot de prefijo ignora los mensajes?#
Es la causa más común. Sin la intent privilegiada Message Content (valor 1 << 15, 32768), Discord entrega vacíos los campos content, embeds, attachments, components y poll. Las excepciones son los mensajes del propio bot, los MD con el bot, los mensajes que mencionan al bot y el mensaje objetivo de un comando de menú contextual.
Por eso message.content.startsWith("!") nunca es verdadero: el bot recibe el evento, pero el texto no llega. Corrígelo en dos lugares:
- En el Developer Portal, página Bot, activa Message Content Intent. Las apps sin verificar la activan directamente. La verificación es obligatoria a partir de 100 servidores, y entonces la intent también tiene que ser aprobada.
- En el código, declara la intent:
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});Si declaras la intent en el código sin activarla en el portal, el Gateway cierra la conexión con el código 4014 (el bot queda desconectado, no mudo). Más detalles en error de intents en el bot de Discord. Si el bot solo necesita comandos, migrar a slash commands elimina la dependencia de esa intent.
¿Por qué el slash command no aparece o no hace nada?#
Un slash command no existe solo porque el bot esté en ejecución. Tiene que registrarse por la API HTTP: PUT /applications/{id}/commands para los globales, PUT /applications/{id}/guilds/{guild_id}/commands para un servidor. Si solo escribiste el handler, Discord no conoce el comando.
Revisa:
- ¿Lo registraste? Los comandos de servidor se actualizan al instante, así que úsalos para probar. Los globales son para producción.
- ¿Invitaste al bot con el scope correcto? Crear comandos en un servidor exige el scope
applications.commands. El scopebotya lo incluye, pero una invitación hecha solo con otros scopes no. - ¿Es el servidor correcto? Un comando registrado en un servidor no existe en los demás ni en los MD.
- Límites: son 100 comandos
CHAT_INPUTglobales y 200 creaciones de comandos por día, por servidor. En lugar de recrearlos uno a uno, usa el bulk overwrite (PUT), que reemplaza la lista entera (los comandos omitidos se eliminan).
¿Por qué aparece "La aplicación no ha respondido"?#
Discord exige una respuesta inicial a la interacción en un máximo de 3 segundos. Pasado ese plazo, el token se invalida y el usuario ve el fallo. Lo mismo ocurre si el handler lanza una excepción antes de responder. Consultar una base de datos, llamar a una API externa o generar una imagen suele superar ese plazo.
La solución es confirmar la interacción primero y responder después:
import { MessageFlags } from "discord.js";
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName !== "informe") return;
try {
await interaction.deferReply(); // responde en menos de 3 s, el usuario ve "pensando..."
const texto = await generarInforme(); // puede tardar
await interaction.editReply(texto); // el token vale 15 minutos
} catch (err) {
console.error(err);
if (interaction.deferred || interaction.replied) {
await interaction.editReply("Algo salió mal.");
} else {
await interaction.reply({ content: "Algo salió mal.", flags: MessageFlags.Ephemeral });
}
}
});El token de la interacción vale 15 minutos para editReply y followUp. Dos errores relacionados aparecen en el log: 10062 Unknown interaction (la interacción expiró) y 40060 Interaction has already been acknowledged (respondiste dos veces; cambia el segundo reply por followUp o editReply).
¿El bot tiene permiso para responder en ese canal?#
Si el evento llega y el código se ejecuta sin errores, pero no aparece nada, puede que el bot no tenga permiso para enviar. En el log ves:
DiscordAPIError[50013]: Missing Permissions
DiscordAPIError[50001]: Missing Access50013 es falta de permiso para la acción (por ejemplo, Send Messages o Embed Links) y 50001 es falta de acceso al canal (View Channel). La causa suele ser un override de permisos en el canal o en la categoría que se impone al rol del bot. Prueba dándole Administrador al rol del bot en un servidor de prueba: si empieza a funcionar, el problema son los permisos, y ajustas lo mínimo necesario. No dejes Administrador en producción.
¿Y si el handler falla en silencio?#
En código async, una excepción sin try/catch se convierte en una promesa rechazada sin manejar. En las versiones actuales de Node.js eso tumba el proceso por defecto, y si algún wrapper se traga el rechazo, el error ni siquiera aparece. Añade process.on("unhandledRejection", console.error) y maneja los errores en el handler, como en el ejemplo de arriba. Revisa también el rate limit: un bucle que envía demasiados mensajes recibe 429 y queda mudo unos segundos, caso explicado en error 429 en Discord.
Por último, los cambios de código solo valen después de reiniciar el proceso. Si editaste el handler y nada cambió, confirma que la versión nueva es la que se está ejecutando.
Cómo hacerlo en Square Cloud#
Para diagnosticar un bot mudo, lo que más necesitas es el log en tiempo real. En Square Cloud aparece en el panel, la CLI, la extensión de VS Code y la app móvil, así que puedes añadir los console.log de arriba, reiniciar y ver el resultado al momento.
El token va en las variables de entorno de la aplicación (panel, API, CLI o VS Code), y el cambio se aplica en el siguiente reinicio, sin rebuild. El hosting acepta discord.js, discord.py, JDA, Discord.Net o cualquier biblioteca de Gateway. Cada aplicación en segundo plano, como un bot, reserva como mínimo 256 MB del pool de RAM del plan.
Consulta la página de hosting de bots de Discord para ver los detalles y los planes.
Hosting de bots
Tu bot en línea 24/7, con reinicio automático
Preguntas frecuentes
¿Por qué mi bot está en línea pero no responde a los !comandos?
El contenido de los mensajes es una intent privilegiada. Sin Message Content activada en el Developer Portal y declarada en el código, el campo content llega vacío y tu prefijo nunca coincide.
¿Qué significa 'La aplicación no ha respondido' en un slash command?
Discord exige una respuesta inicial en un máximo de 3 segundos. Si tu handler tarda más, o lanza un error antes de responder, el usuario ve ese fallo. Usa deferReply() para ganar tiempo.
Mi nuevo slash command no aparece en la lista. ¿Qué hago?
Los comandos solo existen después de registrarlos por la API (PUT en /applications/{id}/commands). Regístralos como comandos de servidor para probar, porque se actualizan al instante, y confirma que invitaste al bot con el scope applications.commands.
El bot responde en mi servidor de prueba pero no en otros. ¿Por qué?
Normalmente son permisos: el bot necesita View Channel y Send Messages en el canal, y un rol o un override puede negarlos. También conviene comprobar si el comando se registró solo en ese servidor.
Más en Bots
Ver los 33 artículos- ¿Cuánto cuesta hospedar un bot de Discord?El costo de hospedar un bot de Discord depende de la RAM, el tiempo en línea, la base de datos y los servicios externos. Aprende a estimar el tuyo.
- Correr un bot en el celular (Termux) o en tu PC vs hospedarloUn bot en tu PC o celular (Termux) se cae cuando el equipo se apaga, se suspende o pierde la red. Compara las tres opciones y cuándo sirve cada una.
- Cómo mantener tu bot de Discord en línea 24/7Para mantener un bot de Discord en línea 24/7, ejecuta el proceso en una máquina siempre encendida con reinicio automático. Compara PC, VPS con pm2 o systemd.
- Por qué tu bot de Discord se apaga o aparece offlineUn bot de Discord aparece offline cuando el proceso se cae, el token es inválido, falta una intent o se acaba la memoria. Diagnostica y corrige cada causa.