{"record":{"id":"bdfc99024cfa24ae","repo":"moeru-ai/airi","slug":"mmd-motion-file-descriptor-name-descript","errorCode":null,"errorMessage":"[mmd] motion file \"${descriptor.name}\" (${descriptor.id}) not found in storage","messagePattern":"\\[mmd\\] motion file \"(.+?)\" \\((.+?)\\) not found in storage","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/stage-ui-mmd/src/components/scenes/MMD.vue","lineNumber":329,"sourceCode":"\n/**\n * Loads and registers any imported VMD motions not yet bound to the current\n * model, then (re)applies the selected idle motion. Safe to call repeatedly;\n * already-registered motions are skipped.\n */\nasync function syncMotions() {\n  if (!animation || !mesh)\n    return\n\n  for (const descriptor of availableMotions.value) {\n    if (registeredMotions.has(descriptor.name))\n      continue\n    try {\n      // The VMD file lives in IndexedDB (shared across windows); build a\n      // window-local object URL to load it, then revoke it once parsed.\n      const file = await mmdStore.getMotionFile(descriptor.id)\n      if (!file) {\n        console.warn(`[mmd] motion file \"${descriptor.name}\" (${descriptor.id}) not found in storage`)\n        continue\n      }\n      const url = URL.createObjectURL(file)\n      try {\n        const clip = await loadMMDAnimationClip(url, mesh)\n        animation.registerClip(descriptor.name, clip)\n        registeredMotions.add(descriptor.name)\n        if (clip.tracks.length === 0) {\n          console.warn(\n            `[mmd] motion \"${descriptor.name}\" loaded but has 0 tracks matching this model. `\n            + 'The VMD\\'s bone/morph names likely do not match the model (different rig/naming).',\n          )\n        }\n      }\n      finally {\n        URL.revokeObjectURL(url)\n      }\n    }","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui-mmd/src/components/scenes/MMD.vue#L311-L347","documentation":"During syncMotions(), the MMD scene iterates availableMotions descriptors and fetches each VMD blob from IndexedDB via mmdStore.getMotionFile(descriptor.id). A descriptor whose blob is missing means the motion list and the blob store are out of sync; that motion is skipped with this warning and sync continues.","triggerScenarios":"availableMotions contains an id whose VMD file is gone from IndexedDB: browser site data cleared or quota-evicted while descriptors persisted elsewhere, a deletion performed in another window (IndexedDB is shared across windows) leaving a stale descriptor, or a storage migration that dropped files but kept descriptors.","commonSituations":"User cleared browsing data or hit storage quota eviction; two app windows open where one deletes a motion; an import interrupted between writing the descriptor and writing the blob.","solutions":["Re-import the missing VMD motion file so the blob exists again for that descriptor","Delete the stale motion entry from the MMD settings list so descriptors match storage","If it recurs across motions, clear the MMD store and re-import to rebuild a consistent state","Request storage persistence (navigator.storage.persist()) so IndexedDB is not evicted under quota pressure"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before registering a motion descriptor\nconst file = await mmdStore.getMotionFile(descriptor.id)\nif (!file) {\n  console.warn(`[mmd] motion file \"${descriptor.name}\" (${descriptor.id}) not found in storage`)\n  await mmdStore.removeMotion(descriptor.id) // prune the stale descriptor\n  continue\n}","typeGuard":"async function hasMotionFile(descriptor: MotionDescriptor): Promise<boolean> {\n  return (await mmdStore.getMotionFile(descriptor.id)) !== undefined\n}","tryCatchPattern":null,"preventionTips":["Write the IndexedDB blob before persisting the descriptor, so interruption cannot orphan one","Prune descriptors whose blobs are missing instead of retrying them every sync","Request navigator.storage.persist() for long-lived local media","When deleting motions, delete from a single window and let other windows refresh their descriptor list"],"tags":["mmd","indexeddb","storage","vmd","stale-descriptor"],"backgroundTag":"indexeddb-record-missing","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}