discordjs/discord.js · error · DiscordjsError
ClientNotReady
ClientNotReady
Error message
The client needs to be logged in to ${action}. What it means
This DiscordjsError (code ClientNotReady) is thrown because generating an invite requires the application's client ID, which is only available after the client has logged in and the READY handshake populated client.application. If this.application is falsy, the client is not logged in yet.
Source
Thrown at packages/discord.js/src/client/Client.js:738
* @example
* const link = client.generateInvite({
* scopes: [OAuth2Scopes.ApplicationsCommands],
* });
* console.log(`Generated application invite link: ${link}`);
* @example
* const link = client.generateInvite({
* permissions: [
* PermissionFlagsBits.SendMessages,
* PermissionFlagsBits.ManageGuild,
* PermissionFlagsBits.MentionEveryone,
* ],
* scopes: [OAuth2Scopes.Bot],
* });
* console.log(`Generated bot invite link: ${link}`);
*/
generateInvite(options = {}) {
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
if (!this.application) throw new DiscordjsError(ErrorCodes.ClientNotReady, 'generate an invite link');
const { scopes } = options;
if (scopes === undefined) {
throw new DiscordjsTypeError(ErrorCodes.InvalidMissingScopes);
}
if (!Array.isArray(scopes)) {
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'scopes', 'Array of Invite Scopes', true);
}
if (!scopes.some(scope => [OAuth2Scopes.Bot, OAuth2Scopes.ApplicationsCommands].includes(scope))) {
throw new DiscordjsTypeError(ErrorCodes.InvalidMissingScopes);
}
if (!scopes.includes(OAuth2Scopes.Bot) && options.permissions) {
throw new DiscordjsTypeError(ErrorCodes.InvalidScopesWithPermissions);
}
View on GitHub (pinned to a81ed8a306)
Solutions
- Call generateInvite only after login completes, e.g. inside the clientReady/ready event handler
- await client.login(token) and chain the invite generation after the promise resolves
- If you only need the link, construct it manually with your application's client ID without needing a live client
Example fix
// before
const link = client.generateInvite({ scopes: [OAuth2Scopes.Bot] });
client.login(token);
// after
client.once('clientReady', () => {
const link = client.generateInvite({ scopes: [OAuth2Scopes.Bot] });
console.log(link);
});
await client.login(token); Defensive patterns
Strategy: try-catch
Validate before calling
if (!client.isReady() || !client.application) {
throw new Error('Cannot generate invite before client is ready');
} Type guard
const canGenerateInvite = (client) => client.isReady() && client.application !== null;
Try / catch
try {
const link = client.generateInvite({ scopes: [OAuth2Scopes.Bot] });
} catch (err) {
if (err.code === 'ClientNotReady') {
// defer or queue the link generation until ready
client.once('clientReady', () => console.log(client.generateInvite({ scopes: [OAuth2Scopes.Bot] })));
} else throw err;
} Prevention
- Generate invite links only inside the clientReady handler
- Never call client APIs at module top level before login
- Check client.isReady() before any application-dependent call
When it happens
Trigger: Calling client.generateInvite(...) before client.login() resolves, during the ClientReady event lag, or in a separate script/instance that never logged in.
Common situations: Constructing the invite link at module top-level instead of inside the ready handler; calling it in another process that shares config but not the live client; a failed login leaving the client half-initialized.
Related errors
- InvalidMissingScopes
- InvalidScopesWithPermissions
- InvalidElement
- ClientMissingIntents
- ClientInvalidOption
AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30).
Data as JSON: /api/errors/bb26fe3dfaec27b7.
Report an issue: GitHub.