moeru-ai/airi · warning
[Spine] Failed to dispose SpineCanvas:
Error message
[Spine] Failed to dispose SpineCanvas:
What it means
disposeSpine() wraps spineCanvas.dispose() in try/catch; the dispose threw — commonly after WebGL context loss or when the update loop still touches resources. After the catch, every reference (assetCleanup, skeleton, animationState, bounds) is cleared and the store's isModelLoaded resets, so component state stays consistent though GPU resources may leak.
Source
Thrown at packages/stage-ui-spine/src/components/scenes/spine/Model.vue:101
// Mutable defaults handed to the animation manager. The manager reads these
// fields on every call, so mutating them in place (see the prop watches
// below) propagates live setting changes without rebuilding the manager.
const animationDefaults = {
mixDuration: props.defaultMixDuration,
idleAnimationEnabled: props.idleAnimationEnabled,
}
const canvas = toRef(() => props.canvas)
const modelSrc = toRef(() => props.modelSrc)
const paused = toRef(() => props.paused)
function disposeSpine() {
if (spineCanvas) {
try {
spineCanvas.dispose()
}
catch (err) {
console.warn('[Spine] Failed to dispose SpineCanvas:', err)
}
spineCanvas = undefined
}
assetCleanup?.()
assetCleanup = undefined
animationManager = undefined
skeleton = undefined
animationState = undefined
modelIntrinsicBounds = undefined
spineStore.isModelLoaded = false
}
async function loadModel() {
await modelLoadMutex.acquire()
modelLoading.value = true
componentState.value = 'loading'
View on GitHub (pinned to 677329427f)
Solutions
- Accept the warning if the app continues normally — state refs are reset regardless
- Stop the render/update loop before disposing the canvas
- Handle webglcontextlost early; dispose-after-loss commonly throws
- Keep the spine runtime version in sync with the asset exporter version
Defensive patterns
Strategy: try-catch
Validate before calling
if (!spineCanvas) return // source guard in disposeSpine
Try / catch
try {
spineCanvas.dispose()
}
catch (err) {
console.warn('[Spine] Failed to dispose SpineCanvas:', err)
}
// always reset refs and store flags afterwards (source pattern) so state stays consistent Prevention
- Stop the render/update loop before dispose() so updates never touch freed resources
- Handle webglcontextlost up front; dispose after context loss commonly throws
- Keep the spine runtime version matched to the asset exporter version
When it happens
Trigger: Unmounting or disposing while the render loop still updates the skeleton; WebGL context already lost; spine runtime version mismatch with exported assets.
Common situations: Scene switching during unmount; tab suspended then resumed with a lost context; spine runtime upgraded without re-exporting assets.
Related errors
- Spine ZIP must contain a .skel or .json skeleton file paired
- Spine ZIP must contain a .atlas (or .atlas.txt) file
- Spine ZIP must contain at least one skeleton+atlas pair
- [Hearing Module] Failed to stop playground monitoring:
- [Spine] No model source provided
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/30159026be3e14ee.
Report an issue: GitHub.