discordjs/discord.js · error · DiscordjsTypeError

InvalidScopesWithPermissions

InvalidScopesWithPermissions

Error message

Permissions cannot be set without the bot scope.

What it means

DiscordjsTypeError with code InvalidScopesWithPermissions is thrown when options.permissions is supplied but the Bot scope is absent from the scopes array. Permissions only make sense for a bot installation, so specifying them without requesting the bot scope is contradictory and rejected.

Source

Thrown at packages/discord.js/src/client/Client.js:754

  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);
    }

    const validScopes = Object.values(OAuth2Scopes);
    const invalidScope = scopes.find(scope => !validScopes.includes(scope));
    if (invalidScope) {
      throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array', 'scopes', invalidScope);
    }

    const query = makeURLSearchParams({
      client_id: this.application.id,
      scope: scopes.join(' '),
      disable_guild_select: options.disableGuildSelect,
    });

    if (options.permissions) {
      const permissions = PermissionsBitField.resolve(options.permissions);
      if (permissions) query.set('permissions', permissions.toString());
    }

View on GitHub (pinned to a81ed8a306)

Solutions

  1. Add OAuth2Scopes.Bot to the scopes array whenever permissions are specified
  2. Remove the permissions option if the invite should not install a bot
  3. Conditionally include permissions only when scopes contain OAuth2Scopes.Bot

Example fix

// before
const link = client.generateInvite({ scopes: [OAuth2Scopes.ApplicationsCommands], permissions: ['ADMINISTRATOR'] });
// after
const link = client.generateInvite({ scopes: [OAuth2Scopes.Bot, OAuth2Scopes.ApplicationsCommands], permissions: ['ADMINISTRATOR'] });
Defensive patterns

Strategy: validation

Validate before calling

if (opts.permissions && !opts.scopes?.includes(OAuth2Scopes.Bot)) {
  throw new Error('permissions require the bot scope');
}

Type guard

const permissionsAreValid = (opts) =>
  !opts.permissions || (Array.isArray(opts.scopes) && opts.scopes.includes(OAuth2Scopes.Bot));

Try / catch

try {
  const link = client.generateInvite(opts);
} catch (err) {
  if (err.code === 'InvalidScopesWithPermissions') opts.scopes = [...opts.scopes, OAuth2Scopes.Bot];
  else throw err;
}

Prevention

When it happens

Trigger: client.generateInvite({ scopes: [OAuth2Scopes.ApplicationsCommands], permissions: ['ADMINISTRATOR'] }) — permissions set while scopes omit OAuth2Scopes.Bot.

Common situations: Adding application-commands scope and permissions together after removing the bot scope; dynamic scope building where permissions are attached unconditionally.

Related errors


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