moeru-ai/airi · error · Error

Cannot find file: ${path}

Error message

Cannot find file: ${path}

What it means

`ZipLoader.readText(jsZip, path)` looks up a file by `path` inside the JSZip instance via `jsZip.file(path)`. If no entry matches (returns a falsy value), it throws `Cannot find file: <path>`. This patched reader is invoked by the Live2D runtime when it tries to load a referenced asset (moc, texture, motion, physics) from the archive.

Source

Thrown at packages/stage-ui-live2d/src/utils/live2d-zip-loader.ts:210

            '': motions.map(motion => ({ File: motion })),
          }
        : undefined,
    },
  })

  settings.name = modelName

  // provide this property for FileLoader
  Object.assign(settings, { _objectURL: `example://${settings.url}` })

  return settings
}

ZipLoader.readText = async (jsZip: JSZip, path: string) => {
  const file = jsZip.file(path)

  if (!file) {
    throw new Error(`Cannot find file: ${path}`)
  }

  const text = await file.async('text')

  return isSettingsFile(path) ? sanitizeModelSettingsText(text) : text
}

const defaultFileLoaderReadText = FileLoader.readText
FileLoader.createSettings = async (files: File[]) => {
  const settingsFile = files.find(file => isSettingsFile(file.webkitRelativePath || file.name))

  if (!settingsFile) {
    throw new TypeError('Settings file not found')
  }

  const settingsUrl = settingsFile.webkitRelativePath || settingsFile.name
  const settingsText = await FileLoader.readText(settingsFile)
  const settings = createModelSettings(settingsText, settingsUrl)

View on GitHub (pinned to 27111382b4)

Solutions

  1. Cross-check every path in `FileReferences` against the actual ZIP entries (case- and separator-sensitive).
  2. Normalize separators to `/` and remove leading `./` in manifest references.
  3. Ensure all referenced assets (moc, textures, motions, physics, pose, display names) are included in the archive.
  4. If a reference is optional, mark it correctly so the runtime does not request it.

Example fix

// before
// manifest Moc: "Model/Moc/model.moc3" but archive has "model.moc3" at root

// after
// align manifest paths with archive layout, or move the file to match
Moc: "model.moc3"
Textures: ["texture_00.png"]
Defensive patterns

Strategy: validation

Validate before calling

const exists = !!zip.file(path)
if (!exists) throw new Error(`Cannot find file: ${path}`)
await ZipLoader.readText(zip, path)

Type guard

function zipHasPath(zip: JSZip, path: string): boolean {
  return !!zip.file(path)
}

Try / catch

try {
  await loadLive2DFromArchive(blob)
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Cannot find file:')) {
    // inspect manifest references vs archive entries
  } else throw e
}

Prevention

When it happens

Trigger: The model manifest references a file (e.g. `FileReferences.Moc` or a texture path) that does not exist in the ZIP, or the path casing/separator differs from the actual archive entry (`\` vs `/`, leading `./`, nested folder mismatch).

Common situations: Manifest edited by hand with a wrong path; model packaged on Windows with backslashes; case-sensitivity mismatch between a macOS-authored manifest and a Linux extractor; a referenced motion/physics file omitted from the archive.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/a1cfe03c5ac611ac. Report an issue: GitHub.