moeru-ai/airi · warning
[mmd] motion file "${descriptor.name}" (${descriptor.id}) no
Error message
[mmd] motion file "${descriptor.name}" (${descriptor.id}) not found in storage What it means
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.
Source
Thrown at packages/stage-ui-mmd/src/components/scenes/MMD.vue:329
/**
* Loads and registers any imported VMD motions not yet bound to the current
* model, then (re)applies the selected idle motion. Safe to call repeatedly;
* already-registered motions are skipped.
*/
async function syncMotions() {
if (!animation || !mesh)
return
for (const descriptor of availableMotions.value) {
if (registeredMotions.has(descriptor.name))
continue
try {
// The VMD file lives in IndexedDB (shared across windows); build a
// window-local object URL to load it, then revoke it once parsed.
const file = await mmdStore.getMotionFile(descriptor.id)
if (!file) {
console.warn(`[mmd] motion file "${descriptor.name}" (${descriptor.id}) not found in storage`)
continue
}
const url = URL.createObjectURL(file)
try {
const clip = await loadMMDAnimationClip(url, mesh)
animation.registerClip(descriptor.name, clip)
registeredMotions.add(descriptor.name)
if (clip.tracks.length === 0) {
console.warn(
`[mmd] motion "${descriptor.name}" loaded but has 0 tracks matching this model. `
+ 'The VMD\'s bone/morph names likely do not match the model (different rig/naming).',
)
}
}
finally {
URL.revokeObjectURL(url)
}
}View on GitHub (pinned to 677329427f)
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
Defensive patterns
Strategy: validation
Validate before calling
// Before registering a motion descriptor
const file = await mmdStore.getMotionFile(descriptor.id)
if (!file) {
console.warn(`[mmd] motion file "${descriptor.name}" (${descriptor.id}) not found in storage`)
await mmdStore.removeMotion(descriptor.id) // prune the stale descriptor
continue
} Type guard
async function hasMotionFile(descriptor: MotionDescriptor): Promise<boolean> {
return (await mmdStore.getMotionFile(descriptor.id)) !== undefined
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- [mmd] motion "${descriptor.name}" loaded but has 0 tracks ma
- MMD ZIP must contain a .pmx or .pmd model file
- [mmd] playAction skipped: "${name}" is not registered
- [mmd] setIdleMotion skipped: "${name}" is not registered
- [mmd] emotion ${emotion} not found
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/bdfc99024cfa24ae.
Report an issue: GitHub.