BabylonJS/Babylon.js · error
Invalid call to preWarmPlayerAsync - player is already playi
Error message
Invalid call to preWarmPlayerAsync - player is already playing or disposed
What it means
preWarmPlayerAsync() prepares the lottie worker player ahead of the actual load. The library throws this error because pre-warming is only valid on a fresh, idle player: if the player is already playing or has been disposed, there is nothing to pre-warm and the call is a programming mistake. It is an explicit guard on _playing/_disposed state at the top of the method.
Source
Thrown at packages/dev/lottiePlayer/src/player.ts:67
* If OffscreenCanvas is not supported by the browser, the animation will not play. Try using LocalLottiePlayer instead.
* @throws Error if OffscreenCanvas is not supported
*/
public constructor() {
// Check if OffscreenCanvas is supported
if (!("OffscreenCanvas" in window)) {
throw new Error("OffscreenCanvas not supported - cannot create Player");
}
}
/**
* Pre-warms the worker and base renderer code. Animation-specific text or image renderer chunks
* load later, after the animation data is known.
* @returns A Promise that resolves to this Player instance when the worker is ready
* @throws Error if the player is already playing or disposed
*/
public async preWarmPlayerAsync(): Promise<Player> {
if (this._playing || this._disposed) {
throw new Error("Invalid call to preWarmPlayerAsync - player is already playing or disposed");
}
if (this._preWarmed) {
return this;
}
// Pre-warming already in progress
if (this._preWarmPromise) {
return await this._preWarmPromise;
}
// Create the promise that will be resolved when we receive the "loaded" message
this._preWarmPromise = new Promise<Player>((resolve, reject) => {
this._preWarmResolve = resolve;
this._preWarmReject = reject;
});
// Initialize worker if not already done
View on GitHub (pinned to 0592b347b8)
Solutions
- Only call preWarmPlayerAsync() immediately after constructing the Player, before play()/load().
- Check player state first: skip the call when player.isDisposed?.() or when playback started.
- Guard the call site with a disposed/playing flag in your component lifecycle.
- Create a fresh Player instance if the old one was disposed.
Example fix
// before
await player.preWarmPlayerAsync();
// after
if (!player._disposed && !player._playing) {
await player.preWarmPlayerAsync();
} Defensive patterns
Strategy: validation
Validate before calling
function canPreWarm(p: Player): boolean {
return !p._disposed && !p._playing;
}
if (canPreWarm(player)) await player.preWarmPlayerAsync(); Type guard
function isPreWarmable(p: Player): p is Player & { _disposed: false; _playing: false } {
return !(p as any)._disposed && !(p as any)._playing;
} Try / catch
try {
await player.preWarmPlayerAsync();
} catch (e) {
if (e instanceof Error && e.message.includes('preWarmPlayerAsync')) {
// player already active — safe to ignore
} else throw e;
} Prevention
- Pre-warm only at construction time, before any play/load call.
- Track disposed state in your app layer and skip pre-warm after dispose.
- Avoid pre-warming in async callbacks that may run after unmount/dispose.
- Cache pre-warmed players and never reuse disposed instances.
When it happens
Trigger: Calling preWarmPlayerAsync() after play() has started (_playing === true) or after dispose() (_disposed === true). Note a second call is safe only via the _preWarmed short-circuit, which is only reachable when not playing/disposed.
Common situations: Pre-warming inside a lifecycle hook that can fire after disposal (e.g. component unmount raced with init); calling pre-warm after the animation already started; reusing a disposed Player instance from a cache.
Related errors
- Engine does not have gl rendering context.
- Atmosphere is not supported on WebGL ${engine.version}.
- Instanced arrays are required for MSDF text rendering.
- There is no NavMesh generated.
- There is no TileCache generated.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/b9fba105ceb78e02.
Report an issue: GitHub.