discordjs/discord.js · error · Error

A client id must be provided to login

Error message

A client id must be provided to login

What it means

The RPC client's login() throws this plain Error when RPCLoginOptions.clientId is missing/empty, before any connection is attempted. The RPC (rich presence) transport needs the OAuth application's client id to authenticate the socket, so login() validates it upfront at client.ts:229.

Source

Thrown at packages/rpc/src/client.ts:229

		return promise;
	}

	/**
	 * Performs authentication flow. Automatically calls Client#connect if needed.
	 *
	 * @example
	 * logging in with a client id and secret
	 * ```ts
	 * client.login({ clientId: '1234567', clientSecret: 'abcdef123' });
	 * ```
	 */
	public async login(
		{ clientId, clientSecret, accessToken }: RPCLoginOptions,
		options?: RequestOptions,
	): Promise<RPCClient> {
		if (!clientId) {
			throw new Error('A client id must be provided to login');
		}

		this.clientId = clientId;

		await this.connect(options);

		if (!this.options.scopes) {
			this.emit(Events.ApplicationReady);
			return this;
		}

		if (accessToken) {
			return this.authenticate(accessToken, options);
		}

		if (!clientSecret) {
			throw new Error('A client secret must be provided for authorization if scopes are included');
		}

View on GitHub (pinned to a81ed8a306)

Solutions

  1. Pass clientId explicitly: client.login({ clientId: 'your-application-id' }) using the application's ID from the Developer Portal.
  2. If loading from env, check it exists before login: if (!process.env.DISCORD_CLIENT_ID) throw ...; and ensure dotenv.config() ran.
  3. Verify the option key is exactly clientId (RPCLoginOptions), not client_id or applicationId.
  4. If you already have an accessToken from a prior OAuth flow, you still must supply clientId alongside it.

Example fix

// before
await client.login({ clientSecret: process.env.CLIENT_SECRET });
// after
if (!process.env.DISCORD_CLIENT_ID) throw new Error('DISCORD_CLIENT_ID is not set');
await client.login({
  clientId: process.env.DISCORD_CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
});
Defensive patterns

Strategy: validation

Validate before calling

function requireClientId(clientId?: string): string {
  if (typeof clientId !== 'string' || clientId.length === 0) {
    throw new Error('clientId is required for RPC login');
  }
  return clientId;
}
// usage
const clientId = requireClientId(process.env.DISCORD_CLIENT_ID);

Type guard

function hasClientId(o: Partial<RPCLoginOptions>): o is RPCLoginOptions & { clientId: string } {
  return typeof o.clientId === 'string' && o.clientId.length > 0;
}

Try / catch

try {
  await client.login(options);
} catch (e) {
  if (e instanceof Error && e.message === 'A client id must be provided to login') {
    console.error('Set clientId in RPCLoginOptions (from the Developer Portal application id)');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling client.login({}) or client.login({ clientSecret, accessToken }) without clientId; passing clientId from an unset environment variable (process.env.DISCORD_CLIENT_ID === undefined); typo in the option key (client_id or applicationId instead of clientId).

Common situations: Rich-presence scripts run without a .env file loaded (dotenv not required first); copying example code that reads env vars that were never set; hardcoding secret but forgetting the public client id; migrating from another RPC library whose option name differs.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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