moeru-ai/airi · error · Error

Failed to ensure MediaPipe vision task asset for ${key}: mis

Error message

Failed to ensure MediaPipe vision task asset for ${key}: missing or empty file at ${outputPath}

What it means

Thrown by prepare-tasks.ts after a download that reportedly succeeded but the target file does not exist or is empty (isUsableFile returns false). This catches the case where downloadAsset resolved without throwing yet the file is unusable - e.g. rename succeeded but the file is zero bytes, or an external process removed it between rename and the check.

Source

Thrown at packages/model-driver-mediapipe/tasks/prepare-tasks.ts:91

  }
  catch (error) {
    throw new Error(`Failed to download MediaPipe vision task asset for ${key} after ${attempt} attempts`, {
      cause: error,
    })
  }
}

await fs.mkdir(assetsRoot, { recursive: true })

for (const { key, source, outputPath } of taskTargets) {
  if (await isUsableFile(outputPath)) {
    console.log(`MediaPipe vision task asset for ${key} already exists at ${outputPath}, skipping download.`)
    continue
  }
  await downloadAsset(key, source, outputPath)

  if (!await isUsableFile(outputPath))
    throw new Error(`Failed to ensure MediaPipe vision task asset for ${key}: missing or empty file at ${outputPath}`)
}

await fs.mkdir(wasmOutputDir, { recursive: true })
await fs.cp(wasmSourceDir, wasmOutputDir, { recursive: true, force: true })

const wasmEntries = await fs.readdir(wasmOutputDir)
if (!wasmEntries.length)
  throw new Error(`Failed to ensure MediaPipe WASM assets: ${wasmOutputDir} is empty`)

console.log('All MediaPipe vision task assets are prepared.')

View on GitHub (pinned to 27111382b4)

Solutions

  1. Inspect outputPath on disk: check size, hash, and content type against the upstream model.
  2. Delete the empty/partial file and rerun the prepare script so downloadAsset runs again.
  3. Disable or allow-list the .task extension in antivirus/sync tools.
  4. Avoid running two prepare-tasks instances against the same assets directory.

Example fix

# before
ls tasks/assets/pose.task  # 0 bytes
# after
rm tasks/assets/pose.task
pnpm -F @proj-airi/model-driver-mediapipe prepare-assets
Defensive patterns

Strategy: validation

Validate before calling

import { stat } from 'node:fs/promises'

async function isUsableFile(path: string): Promise<boolean> {
  try { const s = await stat(path); return s.isFile() && s.size > 0 } catch { return false }
}

if (!await isUsableFile(outputPath)) {
  throw new Error(`Asset at ${outputPath} is missing or empty; rerun prepare-tasks after removing it.`)
}

Try / catch

try {
  await import('./prepare-tasks')
} catch (error) {
  if (error instanceof Error && /missing or empty file/.test(error.message)) {
    // remove the bad file and rerun once
  } else throw error
}

Prevention

When it happens

Trigger: The HTTP response body was empty (HTTP 200 with zero content) and ofetch returned an empty buffer; fs.rename succeeded but the file landed on a broken mount; an antivirus or sync tool quarantined/deleted the file immediately after write; race with another concurrent prepare run.

Common situations: Misconfigured CDN returning 200 + empty body; a proxy stripping the body; antivirus on Windows quarantining unknown .task files; concurrent installs writing to the same path; disk corruption.

Related errors


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