{"record":{"id":"391fceb339e07804","repo":"moeru-ai/airi","slug":"the-magic-live2d-driver-is-not-playing","errorCode":null,"errorMessage":"The MAGIC Live2D driver is not playing.","messagePattern":"The MAGIC Live2D driver is not playing\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/model-driver-magic-live2d/src/driver.ts","lineNumber":122,"sourceCode":"  }\n\n  function start(nextGenerator: Generator<TState>) {\n    if (generator)\n      throw new Error('The MAGIC Live2D driver is already playing.')\n\n    generator = nextGenerator\n    accumulatedMs = 0\n    lastFrameAt = now()\n    filter.reset()\n    outputFrame = undefined\n    options.onOutput?.(undefined)\n    applyPose(generatePose())\n    animationFrame = requestFrame(generationFrame)\n  }\n\n  function replace(nextGenerator: Generator<TState>) {\n    if (!generator)\n      throw new Error('The MAGIC Live2D driver is not playing.')\n\n    generator = nextGenerator\n    accumulatedMs = 0\n    lastFrameAt = now()\n  }\n\n  function stop() {\n    if (!generator)\n      return\n\n    if (animationFrame !== undefined)\n      cancelFrame(animationFrame)\n    generator = undefined\n    animationFrame = undefined\n    accumulatedMs = 0\n    filter.reset()\n    outputFrame = undefined\n    options.onOutput?.(undefined)","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/moeru-ai/airi/blob/9c213115f8bd0fff9e6eabab02b077ac32da21be/packages/model-driver-magic-live2d/src/driver.ts#L104-L140","documentation":"`replace()` swaps the state generator of a driver that is currently animating. If no animation is running (the internal `generator` is undefined), there is nothing to replace and the driver throws instead of silently starting. Use `start()` to begin playback from idle.","triggerScenarios":"Calling `driver.replace(gen)` before any `start()` call, or after `stop()` has cleared the generator. E.g. calling `replace` during component setup before the animation loop was ever started.","commonSituations":"Calling replace in an init path that runs before start; calling replace after an error path already stopped the driver; race where a stop happened between user intent and replace.","solutions":["Call `driver.start(generator)` instead of `replace()` when the driver is idle.","Track playing state and branch: `playing ? replace(g) : start(g)`.","Ensure `start()` is invoked in the mount/lifecycle path before any `replace()` calls can fire.","Check that a prior `stop()` (explicit or from an error handler) did not retire the driver unexpectedly."],"exampleFix":"// before\ndriver.replace(generator)\n// after\nif (driver.isPlaying())\n  driver.replace(generator)\nelse\n  driver.start(generator)","handlingStrategy":"validation","validationCode":"function canReplace(driver: MagicLive2dDriver): boolean {\n  return driver.isPlaying()\n}","typeGuard":null,"tryCatchPattern":"try {\n  driver.replace(generator)\n} catch (error) {\n  if (error instanceof Error && error.message.includes('not playing')) {\n    driver.start(generator)\n  } else {\n    throw error\n  }\n}","preventionTips":["Only call replace() after a confirmed start().","Initialize the driver with start() in your mount path before any dynamic updates.","Track lifecycle state (idle/playing/stopped) explicitly in app state.","Avoid calling replace() from error handlers that may have already stopped the driver."],"tags":["lifecycle","state-error","live2d","animation"],"backgroundTag":"driver-not-running","analyzedSha":"9c213115f8bd0fff9e6eabab02b077ac32da21be","analyzedAt":"2026-09-02T04:27:24.639Z","contentChangedAt":"2026-09-02T04:27:24.639Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}