moeru-ai/airi · error · Error
Failed to download MediaPipe vision task asset for ${key} af
Error message
Failed to download MediaPipe vision task asset for ${key} after ${attempt} attempts What it means
Thrown by downloadAsset() in prepare-tasks.ts after withRetry exhausts all attempts to download a MediaPipe vision task model. The thrown Error wraps the last failure via { cause: error }. The script is a top-level-await build preparation step that fetches pose/hand/face .task model files from storage.googleapis.com.
Source
Thrown at packages/model-driver-mediapipe/tasks/prepare-tasks.ts:75
await fs.writeFile(tempPath, Buffer.from(response))
await fs.rename(tempPath, outputPath)
console.log(`MediaPipe vision task asset for ${key} saved to ${outputPath}`)
}
finally {
await fs.rm(tempPath, { force: true })
}
}, {
onError: (error) => {
const message = errorMessageFromValue(error)
console.warn(`Failed to download MediaPipe vision task asset for ${key} (attempt ${attempt}): ${message}`)
},
})
try {
await downloadWithRetry()
}
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}`)
}
View on GitHub (pinned to 27111382b4)
Solutions
- Retry the build/install once the network is stable; the script resumes and skips already-downloaded files via isUsableFile.
- Pre-download the three .task files on a connected machine and commit or vendor them under packages/model-driver-mediapipe/tasks/assets.
- Allow-list https://storage.googleapis.com on proxies/CI firewalls.
- Inspect error.cause for the underlying fetch error to distinguish network vs. disk vs. HTTP status.
Example fix
# before: fails offline pnpm -F @proj-airi/model-driver-mediapipe prepare-assets # after: pre-place the assets so no download is needed mkdir -p packages/model-driver-mediapipe/tasks/assets cp /cached/pose_landmarker_lite.task packages/model-driver-mediapipe/tasks/assets/ pnpm -F @proj-airi/model-driver-mediapipe prepare-assets
Defensive patterns
Strategy: retry
Validate before calling
// Pre-check network reachability and cache presence before running prepare-tasks
import { existsSync } from 'node:fs'
const required = ['pose.task', 'hand.task', 'face.task']
if (required.every(f => existsSync(`tasks/assets/${f}`))) {
// assets cached; prepare-tasks will skip downloads
} else if (!(await isReachable('storage.googleapis.com'))) {
throw new Error('MediaPipe CDN unreachable; cache assets or fix network before building')
} Try / catch
try {
await import('./prepare-tasks')
} catch (error) {
if (error instanceof Error && /Failed to download MediaPipe/.test(error.message)) {
console.error('Asset download failed. Cause:', error.cause)
// instruct user to cache assets or fix network; then re-run
}
throw error
} Prevention
- Vendor the .task files in CI to avoid runtime downloads.
- Allow-list https://storage.googleapis.com on corporate networks.
- Inspect error.cause to distinguish network, HTTP status, and disk failures.
When it happens
Trigger: Running the prepare-tasks script (postinstall or build) with no/slow network; DNS or TLS failure to storage.googleapis.com; a model URL changed or is rate-limited (HTTP 429); corporate proxy blocks the request; disk full so fs.writeFile fails each attempt.
Common situations: CI behind a firewall without allow-listing the MediaPipe CDN; flaky home network during install; offline build attempted without pre-cached assets; the upstream Google storage bucket is temporarily unavailable.
Related errors
- Failed to ensure MediaPipe vision task asset for ${key}: mis
- Failed to ensure MediaPipe WASM assets: ${wasmOutputDir} is
- No candidate server channel URL was reachable. ${errors.join
- Token exchange failed (${response.status}): ${text}
- No reachable private LAN address is available for the curren
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/50d4b01adc73fada.
Report an issue: GitHub.