moeru-ai/airi · error · Error
Failed to ensure MediaPipe vision task asset for
Error message
Failed to ensure MediaPipe vision task asset for ${key}: missing or empty file at ${outputPath} What it means
After downloadAsset() 'succeeds' (or is skipped because a file existed), prepare-tasks.ts re-validates the output with isUsableFile(outputPath). If the file is missing or zero bytes (a truncated/interrupted download or a pre-existing empty placeholder), it throws this error naming the key and path. It exists to prevent a half-downloaded model from silently breaking FaceLandmarker/PoseLandmarker/HandLandmarker creation at runtime.
Solutions
- Delete the empty/partial file at the reported outputPath and re-run the prepare task with a healthy network.
- Check disk space on the target volume — truncated writes often come from ENOSPC.
- Verify the URL returns real bytes: curl -fL <source> -o <outputPath> manually, then re-run the script so the skip branch validates it.
- On CI, cache the assets directory so downloads rarely re-run.
Defensive patterns
Strategy: retry
Validate before calling
import { stat } from 'node:fs/promises'
async function isUsableFile(path: string): Promise<boolean> {
try {
return (await stat(path)).size > 0
} catch {
return false
}
}
// run before the build task; delete empties so the script re-downloads
if (await isUsableFile(outputPath) === false) await rm(outputPath).catch(() => {}) Prevention
- Delete zero-byte files under the assets directory before re-running the prepare task — the skip branch treats empty files as absent and re-downloads, but a stale empty file from an interrupted run is the usual culprit.
- Monitor disk space on CI; truncated writes are typically ENOSPC.
- Verify downloads manually with curl -fL when a proxy is suspected of returning empty 200s.
When it happens
Trigger: A previous run was killed mid-download leaving an empty file that later runs' isUsableFile skip-check would have caught — but here the fresh download itself ends with an empty/absent file (server returned an empty body, disk full, or the write was interrupted). Also possible when a proxy or captive portal returns an empty 200.
Common situations: Disk-full CI runners; captive Wi-Fi portals returning empty responses; interrupted first download that left a 0-byte file which the skip branch then short-circuits on the next run (remove it); antivirus quarantining the file immediately after write.
Related errors
- Failed to download MediaPipe vision task asset for
- Failed to ensure MediaPipe WASM assets
- Extension copy does not match the reviewed package.
- Extension is already installed
- Extension manifest does not exist
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/4112fb942fc91c11.
Report an issue: GitHub.
Appendix: 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 677329427f)