discordjs/discord.js · error · Error
Token has already been set
Error message
Token has already been set
What it means
setToken() refuses to overwrite an existing token and throws if this.#token is already set. The manager treats the token as immutable once configured to prevent inconsistent auth state across shards.
Source
Thrown at packages/ws/src/ws/WebSocketManager.ts:376
await this.updateShardCount(shardCount);
const shardIds = await this.getShardIds();
const data = await this.fetchGatewayInformation();
if (data.session_start_limit.remaining < shardIds.length) {
throw new Error(
`Not enough sessions remaining to spawn ${shardIds.length} shards; only ${
data.session_start_limit.remaining
} remaining; resets at ${new Date(Date.now() + data.session_start_limit.reset_after).toISOString()}`,
);
}
await this.strategy.connect();
}
public setToken(token: string): void {
if (this.#token) {
throw new Error('Token has already been set');
}
this.#token = token;
}
public destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {
return this.strategy.destroy(options);
}
public send(shardId: number, payload: GatewaySendPayload) {
return this.strategy.send(shardId, payload);
}
public fetchStatus(): Awaitable<Collection<number, WebSocketShardStatus>> {
return this.strategy.fetchStatus();
}
public async [Symbol.asyncDispose]() {View on GitHub (pinned to a81ed8a306)
Solutions
- Call setToken only once, at initialization
- Destroy the existing manager and create a new one if the token must change
- Guard the call: only setToken if no token was set yet (token getter throws when unset, so track it yourself)
Example fix
// before
manager.setToken(newToken); // throws if already set
// after
try {
manager.setToken(newToken);
} catch {
// token already set — destroy and rebuild if a change is truly required
await manager.destroy();
manager = new WebSocketManager(options);
manager.setToken(newToken);
} Defensive patterns
Strategy: validation
Validate before calling
let tokenApplied = false;
function safeSetToken(manager: WebSocketManager, token: string): void {
if (!tokenApplied) {
manager.setToken(token);
tokenApplied = true;
}
} Try / catch
try {
manager.setToken(newToken);
} catch (e) {
if (e instanceof Error && e.message.includes('already been set')) {
// token is immutable; ignore or recreate the manager
} else throw e;
} Prevention
- Set the token exactly once during bootstrap
- For token rotation, destroy() the manager and build a new instance
- Keep manager construction in a single init path, not in handlers
When it happens
Trigger: Calling manager.setToken(...) a second time on the same WebSocketManager instance, e.g. during a config reload or when reusing a cached manager instance.
Common situations: Hot-reloading configuration code that re-runs setToken(); accidentally constructing once globally but calling setToken in a per-request/per-event handler; unit tests reusing a module-level manager.
Related errors
- Expected token to be set for this request, but none was pres
- Token has not been set
- Package ${packageName} not releaseable
- The --tag option can only be used with --dev
- ClientMissingIntents
AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30).
Data as JSON: /api/errors/079420bfe0aba731.
Report an issue: GitHub.