discordjs/discord.js · error · Error
No session available
Error message
No session available
What it means
setExternalSender() requires an active underlying MLS session; when this.session is null (not yet initialized), it throws 'No session available'. The MLS external sender payload can only be applied to an initialized session.
Source
Thrown at packages/voice/src/networking/DAVESession.ts:183
this.session = new Davey.DAVESession(this.protocolVersion, this.userId, this.channelId);
this.emit('debug', `Session initialized for protocol version ${this.protocolVersion}`);
}
this.emit('keyPackage', this.session!.getSerializedKeyPackage());
} else if (this.session) {
this.session.reset();
this.session.setPassthroughMode(true, TRANSITION_EXPIRY);
this.emit('debug', 'Session reset');
}
}
/**
* Set the external sender for this session.
*
* @param externalSender - The external sender
*/
public setExternalSender(externalSender: Buffer) {
if (!this.session) throw new Error('No session available');
this.session.setExternalSender(externalSender);
this.emit('debug', 'Set MLS external sender');
}
/**
* Prepare for a transition.
*
* @param data - The transition data
* @returns Whether we should signal to the voice server that we are ready
*/
public prepareTransition(data: VoiceDavePrepareTransitionData) {
this.emit('debug', `Preparing for transition (${data.transition_id}, v${data.protocol_version})`);
this.pendingTransitions.set(data.transition_id, data.protocol_version);
// When the included transition id is 0, the transition is for (re)initialization and it can be executed immediately.
if (data.transition_id === 0) {
this.executeTransition(data.transition_id);
} else {View on GitHub (pinned to a81ed8a306)
Solutions
- Ensure the session is initialized/ready before handling the external sender message
- Buffer the external sender payload and apply it on session ready
- Install/repair the @snazzah/davey dependency so initialization succeeds
- Reinitialize the DAVE session and re-send the external sender
Example fix
// before session.setExternalSender(payload); // after if (session.isReady()) session.setExternalSender(payload); else pendingExternalSender = payload; // apply once ready
Defensive patterns
Strategy: try-catch
Validate before calling
function canSetSender(s) { return (s as any).session != null; }
if (canSetSender(dave)) dave.setExternalSender(payload); else pendingSender = payload; Type guard
function hasActiveSession(s: { session?: unknown }): boolean { return s.session != null; } Try / catch
try { dave.setExternalSender(buf); } catch (e) { if (e.message === 'No session available') pendingSender = buf; else throw e; } Prevention
- Queue binary payloads (external sender) until session ready
- Listen for session init/ready events from DAVESession
- Keep @snazzah/davey installed at the supported version
- Re-apply external sender after each reinit if required
When it happens
Trigger: Calling setExternalSender(buffer) (directly or via the binary websocket handler onWsBinary) before the DAVE session has finished initializing, or after it was destroyed.
Common situations: Voice gateway delivers the MLS external sender payload before session setup completes; session init failed due to a missing/incompatible @snazzah/davey install; race between gateway messages and session readiness.
Related errors
- Session not available
- Cannot destroy VoiceConnection - it has already been destroy
- ClientNotReady
- Session not available
- No compatible encryption modes. Available include: ${options
AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30).
Data as JSON: /api/errors/9e0220e7f5135ee8.
Report an issue: GitHub.