moeru-ai/airi · error · Error

Textures not found

Error message

Textures not found

What it means

Inside `createFakeSettings`, after locating the single moc file, the loader filters `files` for `.png` entries as textures. If none are found it throws `Textures not found`. A Cubism model requires at least one texture page; the synthetic manifest cannot be built without one.

Source

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

}

// copy and modified from https://github.com/guansss/live2d-viewer-web/blob/f6060b2ce52c2e26b6b61fa903c837fe343f72d1/src/app/upload.ts#L81-L142
function createFakeSettings(files: string[]): ModelSettings {
  const mocFiles = files.filter(file => isMocFile(file))

  if (mocFiles.length !== 1) {
    const fileList = mocFiles.length ? `(${mocFiles.map(f => `"${f}"`).join(',')})` : ''

    throw new Error(`Expected exactly one moc file, got ${mocFiles.length} ${fileList}`)
  }

  const mocFile = mocFiles[0]
  const modelName = basename(mocFile).replace(/\.moc3?/, '')

  const textures = files.filter(f => f.endsWith('.png'))

  if (!textures.length) {
    throw new Error('Textures not found')
  }

  const motions = files.filter(f => f.endsWith('.mtn') || f.endsWith('.motion3.json'))
  const physics = files.find(f => f.includes('physics'))
  const pose = files.find(f => f.includes('pose'))

  const settings = new Cubism4ModelSettings({
    url: `${modelName}.model3.json`,
    Version: 3,
    FileReferences: {
      Moc: mocFile,
      Textures: textures,
      Physics: physics,
      Pose: pose,
      Motions: motions.length
        ? {
            '': motions.map(motion => ({ File: motion })),
          }

View on GitHub (pinned to 27111382b4)

Solutions

  1. Confirm the archive contains `.png` texture files alongside the moc.
  2. Re-export from the Live2D Cubism tool ensuring textures are bundled.
  3. If only `.webp`/`.jpg` exist, convert them to `.png` or supply a real `model3.json` that lists the alternate texture URIs.
  4. Check for case mismatches and ZIP path issues (folders, backslashes).

Example fix

// before
// archive has moc but textures are .webp only -> throws

// after
// ensure at least one .png ships in the archive
const textures = files.filter(f => f.toLowerCase().endsWith('.png'))
if (!textures.length) throw new Error('Archive must include at least one .png texture')
Defensive patterns

Strategy: validation

Validate before calling

const textures = files.filter(f => f.toLowerCase().endsWith('.png'))
if (!textures.length)
  throw new Error('Archive must include at least one .png texture')
createFakeSettings(files)

Type guard

function hasPngTextures(files: string[]): boolean {
  return files.some(f => f.toLowerCase().endsWith('.png'))
}

Try / catch

try {
  await loadLive2DFromArchive(blob)
} catch (e) {
  if (e instanceof Error && e.message === 'Textures not found') {
    // ask user to include .png textures
  } else throw e
}

Prevention

When it happens

Trigger: An archive that has a moc but no `.png` textures — textures were omitted, stored in an unsupported format (e.g. `.webp`/`.jpg` only), placed in a nested folder the flat filter still sees but with wrong casing, or stripped during packaging.

Common situations: Texture files renamed to non-png formats; an archive where textures live in a folder that was excluded; case-sensitivity on a case-sensitive filesystem (`.PNG` vs `.png` is matched, but typos like `.pn` fail); a model exported with textures referenced but not bundled.

Related errors


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