airbnb/lottie-web · error · Error

Cannot set data on wrapper for canvas worker renderer

Error message

Cannot set data on wrapper for canvas worker renderer

What it means

The worker build overrides AnimationItem.prototype.setData to always throw. setData normally binds a DOM element (scanning it for data attributes / embedded JSON), which is meaningless in a worker where no document exists. registerAnimation() and searchAnimations() both end up calling setData, so any DOM-driven registration path is disabled by design.

Source

Thrown at player/js/animation/AnimationItemWorkerOverride.js:53

  } else {
    this.loop = parseInt(params.loop, 10);
  }
  this.autoplay = 'autoplay' in params ? params.autoplay : true;
  this.name = params.name ? params.name : '';
  this.autoloadSegments = Object.prototype.hasOwnProperty.call(params, 'autoloadSegments') ? params.autoloadSegments : true;
  this.assetsPath = null;
  if (params.animationData) {
    dataManager.completeAnimation(
      params.animationData,
      this.configAnimation
    );
  } else if (params.path) {
    throw new Error('Canvas worker renderer cannot load animation from url');
  }
};

AnimationItem.prototype.setData = function () {
  throw new Error('Cannot set data on wrapper for canvas worker renderer');
};

AnimationItem.prototype.includeLayers = function (data) {
  if (data.op > this.animationData.op) {
    this.animationData.op = data.op;
    this.totalFrames = Math.floor(data.op - this.animationData.ip);
  }
  var layers = this.animationData.layers;
  var i;
  var len = layers.length;
  var newLayers = data.layers;
  var j;
  var jLen = newLayers.length;
  for (j = 0; j < jLen; j += 1) {
    i = 0;
    while (i < len) {
      if (layers[i].id === newLayers[j].id) {
        layers[i] = newLayers[j];

View on GitHub (pinned to bede03d25d)

Solutions

  1. Use lottie.loadAnimation({ renderer: 'canvas', animationData }) inside the worker instead of registerAnimation/searchAnimations.
  2. Keep registerAnimation and searchAnimations on the main thread and only delegate rendering to the worker via the worker bridge.
  3. Remove or feature-gate any searchAnimations/registerAnimation calls when running inside a Worker (typeof document === 'undefined').

Example fix

// before (worker build)
lottie.registerAnimation(myDomElement, animationData);
// after
lottie.loadAnimation({ renderer: 'canvas', animationData, loop: true, autoplay: true });
Defensive patterns

Strategy: validation

Validate before calling

function safeLottieCall(lottie, isWorker) {
  if (isWorker) {
    return function (params) { return lottie.loadAnimation(params); }; // loadAnimation only
  }
  return null; // registerAnimation/searchAnimations are fine on main thread
}
// guard call sites
if (!isWorker) { lottie.registerAnimation(el, animationData); }
else { lottie.loadAnimation({ renderer: 'canvas', animationData }); }

Type guard

function canUseDomRegistration() {
  return typeof document !== 'undefined' && typeof document.getElementsByTagName === 'function';
}

Prevention

When it happens

Trigger: Calling lottie.registerAnimation(element, animationData) with the worker build; calling lottie.searchAnimations() (which internally registers elements); any internal code path that reaches setData. These are main-thread/DOM APIs that have no worker equivalent.

Common situations: Using the worker build but keeping a main-thread-style call (registerAnimation/searchAnimations) in shared code; auto-search logic running in a worker; copy-pasting an integration that relies on data-anim-type attributes in markup.

Related errors


AI-assisted analysis of airbnb/lottie-web@bede03d25d (2026-08-13). Data as JSON: /api/errors/ff65642bb99699fe. Report an issue: GitHub.