{"record":{"id":"637ea6aa3d890203","repo":"moeru-ai/airi","slug":"mmd-setidlemotion-skipped-name-is-not-regi","errorCode":null,"errorMessage":"[mmd] setIdleMotion skipped: \"${name}\" is not registered","messagePattern":"\\[mmd\\] setIdleMotion skipped: \"(.+?)\" is not registered","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/stage-ui-mmd/src/composables/mmd/animation-manager.ts","lineNumber":183,"sourceCode":"    currentAction = action\n\n    if (loop)\n      removeFinishListener(action)\n    else\n      revertToIdleOnFinish(action)\n\n    return true\n  }\n\n  /**\n   * Makes a registered motion the looping base that one-shots return to.\n   *\n   * @returns `false` when no clip is registered under `name`.\n   */\n  function setIdleMotion(name: string, crossfade = DEFAULT_CROSSFADE): boolean {\n    const clip = registry.get(name)\n    if (!clip) {\n      console.warn(`[mmd] setIdleMotion skipped: \"${name}\" is not registered`)\n      return false\n    }\n\n    const action = mixer.clipAction(clip)\n    action.reset()\n    action.setLoop(LoopRepeat, Number.POSITIVE_INFINITY)\n    action.clampWhenFinished = false\n    action.setEffectiveWeight(1)\n    action.fadeIn(crossfade).play()\n\n    const previousIdle = idleAction\n    idleAction = action\n    if (currentAction && currentAction !== action) {\n      removeFinishListener(currentAction)\n      currentAction.fadeOut(crossfade)\n    }\n    else if (previousIdle && previousIdle !== action) {\n      previousIdle.fadeOut(crossfade)","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui-mmd/src/composables/mmd/animation-manager.ts#L165-L201","documentation":"setIdleMotion promotes a registered clip to the looping base that one-shot motions return to. Like playAction it looks the name up in the clip registry; on a miss it warns and returns false, leaving the previous idle action (if any) in place — the API is total, never throwing.","triggerScenarios":"Passing a name to setIdleMotion that was never registered via registerClip: typo, motion import not finished, or a settings file referencing a motion that isn't part of the loaded model.","commonSituations":"Persisted user settings naming an idle motion that no longer exists in the current model files; startup code setting idle before the VMD import resolves.","solutions":["Ensure registerClip ran for the idle clip before setIdleMotion (await model/import readiness)","Use the boolean return to detect the miss and keep the existing idle, or fall back to a known-registered default","Validate configured motion names against availableClips() when loading settings"],"exampleFix":"// before\nanimation.setIdleMotion('stand_by') // not registered -> previous idle (or none) kept\n\n// after\nconst clips = animation.availableClips()\nif (!clips.includes('stand_by')) {\n  console.warn('idle motion stand_by missing, using', clips[0])\n  animation.setIdleMotion(clips[0])\n}\nelse {\n  animation.setIdleMotion('stand_by')\n}","handlingStrategy":"validation","validationCode":"const registered = animation.availableClips()\nconst idleName = registered.includes(configuredIdle) ? configuredIdle : registered[0]\nanimation.setIdleMotion(idleName)","typeGuard":"function isRegisteredMotion(manager: { availableClips(): string[] }, name: string): name is string {\n  return manager.availableClips().includes(name)\n}","tryCatchPattern":null,"preventionTips":["Await model import completion before configuring the idle motion","Fall back to a known-registered clip when the configured name misses","Surface availableClips() in settings UIs so users pick valid names"],"tags":["mmd","threejs","animation","idle-motion","registry"],"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"}