moeru-ai/airi · error

No VRM animation loaded

Error message

No VRM animation loaded

What it means

After the VRM loads, the component loads the idle animation via loadVRMAnimation(idleAnimation) and converts it with clipFromVRMAnimation. loadVRMAnimation returns undefined when the .vrma file's gltf.userData has no vrmAnimations (the file is not a valid VRMA or contains zero VRM animation entries), so the clip is undefined. The component then disposes the half-loaded VRM, reports the load as failed and emits an 'error' event — the model does not appear.

Source

Thrown at packages/stage-ui-three/src/components/Model/VRMModel.vue:778

      camera: camera.value,
      reason: currentLoadReason,
      vrm: _vrm,
      vrmGroup: _vrmGroup,
    })

    /*
      * Animation setting
    */
    const animation = await loadVRMAnimation(idleAnimation.value)
    const clip = await clipFromVRMAnimation(_vrm, animation)
    if (!isLoadRequestCurrent(requestId)) {
      disposeDetachedVrm(nextVrm, nextVrmGroup)
      return
    }
    if (!clip) {
      disposeDetachedVrm(nextVrm, nextVrmGroup)
      emitVrmLoadError(currentLoadReason, loadStartedAt, 'No VRM animation loaded')
      console.warn('No VRM animation loaded')
      if (isLoadRequestCurrent(requestId))
        emit('error', new Error('No VRM animation loaded'))
      return
    }
    // Re-anchor the root position track to the model origin
    reAnchorRootPositionTrack(clip, _vrm)

    // play animation
    nextVrmAnimationMixer = new AnimationMixer(_vrm.scene)
    nextVrmAnimationMixer.clipAction(clip).play()

    nextVrmEmote = useVRMEmote(_vrm)

    /*
      * Shader setting
    */
    const isShaderMat = (m: any): m is ShaderMaterial => !!m?.isShaderMaterial

View on GitHub (pinned to 677329427f)

Solutions

  1. Verify the idleAnimation URL actually serves a valid .vrma (check the network tab; it must parse as glTF containing VRM animation extensions)
  2. Re-supply a known-good VRMA idle file (e.g. the bundled idle loop) and reload
  3. Handle the component's 'error' event in the parent to surface the failure instead of a blank scene
  4. If authoring your own file, export at least one VRM animation into the .vrma

Example fix

// before
const animation = await loadVRMAnimation(idleAnimation.value)
const clip = await clipFromVRMAnimation(_vrm, animation)

// after
const animation = await loadVRMAnimation(idleAnimation.value)
const clip = await clipFromVRMAnimation(_vrm, animation)
if (!clip) {
  throw new Error(`Idle animation at ${idleAnimation.value} is not a valid .vrma with at least one VRM animation`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the .vrma before use
const gltf = await useVRMLoader().loadAsync(url)
const animations = (gltf.userData as GLTFUserdata).vrmAnimations
if (!animations || animations.length === 0) {
  throw new Error(`File at ${url} is not a valid .vrma containing VRM animations`)
}

Type guard

function isVRMAUserData(userData: unknown): userData is GLTFUserdata {
  return Boolean(userData) && typeof userData === 'object'
    && Array.isArray((userData as GLTFUserdata).vrmAnimations)
    && (userData as GLTFUserdata).vrmAnimations.length > 0
}

Try / catch

try {
  const animation = await loadVRMAnimation(idleAnimation.value)
  const clip = await clipFromVRMAnimation(vrm, animation)
  if (!clip)
    throw new Error('No VRM animation loaded')
}
catch (error) {
  // Distinguish asset-invalid from network failure before deciding to refetch or fall back to a bundled idle
  emit('error', error instanceof Error ? error : new Error(String(error)))
}

Prevention

When it happens

Trigger: The idleAnimation URL points at a file that is not a valid .vrma: a plain glb/gltf, a truncated download, an HTML error page served in place of the asset, or a genuine .vrma whose vrmAnimations array is empty.

Common situations: Bundled default idle animation missing or corrupted in the deployment; passing a generic glTF animation instead of a VRMA; a build step or CDN dropping/mangling the .vrma asset.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/5ccdf143eeab577a. Report an issue: GitHub.