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

  1. Call generateInvite only after login completes, e.g. inside the clientReady/ready event handler
  2. await client.login(token) and chain the invite generation after the promise resolves
  3. 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

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


AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30). Data as JSON: /api/errors/bb26fe3dfaec27b7. Report an issue: GitHub.