{"record":{"id":"2c49be3ffbad631c","repo":"moeru-ai/airi","slug":"mmd-playaction-skipped-name-is-not-registe","errorCode":null,"errorMessage":"[mmd] playAction skipped: \"${name}\" is not registered","messagePattern":"\\[mmd\\] playAction skipped: \"(.+?)\" is not registered","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/stage-ui-mmd/src/composables/mmd/animation-manager.ts","lineNumber":148,"sourceCode":"    }\n\n    if (currentAction && currentAction !== idleAction)\n      currentAction.fadeOut(crossfade)\n    // A one-shot may reuse the same action, so restore its looping contract.\n    idleAction.reset().setLoop(LoopRepeat, Number.POSITIVE_INFINITY).setEffectiveWeight(1).fadeIn(crossfade).play()\n    currentAction = idleAction\n  }\n\n  /**\n   * Plays a registered motion and cross-fades from the current action.\n   * One-shots return to idle; looping actions remain active until replaced.\n   *\n   * @returns `false` when no clip is registered under `name`.\n   */\n  function playAction(name: string, actionOptions: PlayActionOptions = {}): boolean {\n    const clip = registry.get(name)\n    if (!clip) {\n      console.warn(`[mmd] playAction skipped: \"${name}\" is not registered`)\n      return false\n    }\n\n    const loop = actionOptions.loop ?? false\n    const crossfade = actionOptions.crossfade ?? DEFAULT_CROSSFADE\n    const action = mixer.clipAction(clip)\n    action.reset()\n    action.setLoop(loop ? LoopRepeat : LoopOnce, loop ? Number.POSITIVE_INFINITY : 1)\n    action.clampWhenFinished = !loop\n    action.setEffectiveWeight(1)\n    action.fadeIn(crossfade).play()\n\n    if (currentAction && currentAction !== action) {\n      removeFinishListener(currentAction)\n      currentAction.fadeOut(crossfade)\n    }\n    currentAction = action\n","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui-mmd/src/composables/mmd/animation-manager.ts#L130-L166","documentation":"The MMD animation manager keeps clips in a Map populated by registerClip(name, clip). playAction(name) looks the name up; when no clip is registered under it, it warns and returns false instead of throwing — the current action is left untouched (idle keeps playing).","triggerScenarios":"Calling playAction with a name never passed to registerClip: typo, case mismatch, a motion file that failed to import, or calling playAction before clip registration finished (e.g. before the VMD import promise resolved).","commonSituations":"Hardcoded motion names that don't match VMD-derived names; user-configurable motion mappings pointing at files that weren't loaded; race between model load and an autoplay trigger.","solutions":["Register the clip with registerClip(name, clip) before calling playAction","Check the boolean return value and fall back (keep idle or try a default motion) instead of assuming playback started","Log availableClips() when the miss happens to catch typos and case mismatches against the real registry keys"],"exampleFix":"// before\nanimation.playAction('Wave') // registry has 'wave' -> skipped, returns false\n\n// after\nif (!animation.playAction('Wave'))\n  animation.playAction(animation.availableClips().find(c => c.toLowerCase() === 'wave') ?? 'idle')","handlingStrategy":"validation","validationCode":"if (!animation.availableClips().includes(name)) {\n  console.warn(`motion ${name} not registered, have:`, animation.availableClips().join(', '))\n  return\n}\nanimation.playAction(name)","typeGuard":"function isRegisteredMotion(manager: { availableClips(): string[] }, name: string): name is string {\n  return manager.availableClips().includes(name)\n}","tryCatchPattern":null,"preventionTips":["Register all clips before exposing playback triggers","Always branch on the boolean return of playAction","Validate persisted motion-name settings against availableClips() on load"],"tags":["mmd","threejs","animation","registry","clip-not-found"],"backgroundTag":"unregistered-animation-clip","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}