{"record":{"id":"4112fb942fc91c11","repo":"moeru-ai/airi","slug":"failed-to-ensure-mediapipe-vision-task-asset-for","errorCode":null,"errorMessage":"Failed to ensure MediaPipe vision task asset for ${key}: missing or empty file at ${outputPath}","messagePattern":"Failed to ensure MediaPipe vision task asset for (.+?): missing or empty file at (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/model-driver-mediapipe/tasks/prepare-tasks.ts","lineNumber":91,"sourceCode":"  }\n  catch (error) {\n    throw new Error(`Failed to download MediaPipe vision task asset for ${key} after ${attempt} attempts`, {\n      cause: error,\n    })\n  }\n}\n\nawait fs.mkdir(assetsRoot, { recursive: true })\n\nfor (const { key, source, outputPath } of taskTargets) {\n  if (await isUsableFile(outputPath)) {\n    console.log(`MediaPipe vision task asset for ${key} already exists at ${outputPath}, skipping download.`)\n    continue\n  }\n  await downloadAsset(key, source, outputPath)\n\n  if (!await isUsableFile(outputPath))\n    throw new Error(`Failed to ensure MediaPipe vision task asset for ${key}: missing or empty file at ${outputPath}`)\n}\n\nawait fs.mkdir(wasmOutputDir, { recursive: true })\nawait fs.cp(wasmSourceDir, wasmOutputDir, { recursive: true, force: true })\n\nconst wasmEntries = await fs.readdir(wasmOutputDir)\nif (!wasmEntries.length)\n  throw new Error(`Failed to ensure MediaPipe WASM assets: ${wasmOutputDir} is empty`)\n\nconsole.log('All MediaPipe vision task assets are prepared.')\n","sourceCodeStart":73,"sourceCodeEnd":102,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/model-driver-mediapipe/tasks/prepare-tasks.ts#L73-L102","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect outputPath on disk: check size, hash, and content type against the upstream model.","Delete the empty/partial file and rerun the prepare script so downloadAsset runs again.","Disable or allow-list the .task extension in antivirus/sync tools.","Avoid running two prepare-tasks instances against the same assets directory."],"exampleFix":"# before\nls tasks/assets/pose.task  # 0 bytes\n# after\nrm tasks/assets/pose.task\npnpm -F @proj-airi/model-driver-mediapipe prepare-assets","handlingStrategy":"validation","validationCode":"import { stat } from 'node:fs/promises'\n\nasync function isUsableFile(path: string): Promise<boolean> {\n  try { const s = await stat(path); return s.isFile() && s.size > 0 } catch { return false }\n}\n\nif (!await isUsableFile(outputPath)) {\n  throw new Error(`Asset at ${outputPath} is missing or empty; rerun prepare-tasks after removing it.`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await import('./prepare-tasks')\n} catch (error) {\n  if (error instanceof Error && /missing or empty file/.test(error.message)) {\n    // remove the bad file and rerun once\n  } else throw error\n}","preventionTips":["Delete zero-byte asset files and rerun prepare-tasks.","Allow-list .task extensions in antivirus/sync tooling.","Run only one prepare-tasks instance against a given assets directory."],"tags":["mediapipe","build","assets","filesystem","download-integrity"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}