moeru-ai/airi · error · Error

MediaPipe backend not initialized (call init() first)

Error message

MediaPipe backend not initialized (call init() first)

What it means

createMediaPipeBackend() in packages/model-driver-mediapipe keeps module-closed state (config, tasksVision, vision FilesetResolver) that is only populated by init(nextConfig). run(frame, jobs, nowMs) throws this error when config is still undefined, i.e. the perception loop started calling run() before anyone awaited init(). The check is the backend's fail-fast contract: landmarks, the WASM fileset, and per-job enablement flags all depend on init having run.

Solutions

  1. Await init(config) before starting the engine loop: const backend = createMediaPipeBackend(); await backend.init(config); engine.start(backend).
  2. If init is async and unavoidable in parallel with the loop, guard run calls or buffer frames until a ready flag flips (the engine already drops frames when isBusy() is true — also respect readiness).
  3. On component teardown/re-mount, re-init the new backend instance because the old instance's config does not transfer.

Example fix

// before
const backend = createMediaPipeBackend()
engine.start(backend) // first run() throws: init never awaited
await backend.init(config)

// after
const backend = createMediaPipeBackend()
await backend.init(config)
engine.start(backend)
Defensive patterns

Strategy: validation

Validate before calling

const backend = createMediaPipeBackend()
const ready = backend.init(config) // promise
await ready // block the loop start on successful init
engine.start(backend)

Prevention

When it happens

Trigger: Calling backend.run() (directly or via createMocapEngine's scheduler) without awaiting createMediaPipeBackend().init(config) first; init() still in flight (dynamic import of @mediapipe/tasks-vision + FilesetResolver.forVisionTasks) when the first animation frame triggers run; a code path that constructs a fresh backend per component mount but only inits it on a branch that did not execute.

Common situations: A Vue composable starts the rAF loop in onMounted but awaits init in a later tick or a conditional; hot-reload during development re-creates the backend without re-running init; engine wired up in devtools before the async init promise resolves.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/7f563ec9dcc40e6a. Report an issue: GitHub.

Appendix: source

Thrown at packages/model-driver-mediapipe/src/backends/mediapipe.ts:90

  }

  async function ensureFaceLandmarker() {
    if (faceLandmarker)
      return faceLandmarker

    const { FaceLandmarker } = tasksVision!
    faceLandmarker = await FaceLandmarker.createFromOptions(vision!, {
      baseOptions: { modelAssetPath: visionTaskAssets.face },
      runningMode: 'VIDEO',
      numFaces: 1,
    })

    return faceLandmarker
  }

  async function run(frame: TexImageSource, jobs: MocapJob[], nowMs: number): Promise<PerceptionPartial> {
    if (!config)
      throw new Error('MediaPipe backend not initialized (call init() first)')

    await semaphore.acquire()
    busy = true
    try {
      const partial: PerceptionPartial = {}

      for (const job of jobs) {
        if (!config.enabled[job])
          continue

        if (job === 'pose') {
          const landmarker = await ensurePoseLandmarker()
          const res: PoseLandmarkerResult = landmarker.detectForVideo(frame, nowMs)
          const firstPose: NormalizedLandmark[] = res.landmarks[0] ?? []
          const firstWorld: Landmark[] = res.worldLandmarks[0] ?? []
          partial.pose = {
            landmarks2d: firstPose,
            worldLandmarks: firstWorld.map(p => ({

View on GitHub (pinned to 677329427f)