RiggyTry it

Spine: Cannot read properties of undefined (reading 'bones')

spine-ts (web, Phaser, PixiJS)
TypeError: Cannot read properties of undefined (reading 'bones') — SkeletonJson.readAnimation — reads the attachment without a check
spine-csharp (Unity)
Timeline attachment not found: head-mesh — SkeletonJson.ReadAnimation

An animation has deform keys for an attachment that does not exist in the named skin and slot, or that is not a mesh. Animations are parsed while the skeleton loads, so this breaks the whole skeleton, not one animation.

Where the runtime breaks

In Spine 4.2 deform keys live under animations → attachments → skin → slot → attachment. The spine-ts loader takes the attachment from that skin and reads its bones without checking that it exists, so a missing attachment becomes a TypeError. In Chrome and Node it reads Cannot read properties of undefined (reading 'bones'); other browsers word it differently. When the attachment exists but is a plain region, not a mesh, the same place fails on reading 'length'. The C# runtime checks and names the attachment: Timeline attachment not found.

"animations": {
  "blink": {
    "attachments": {
      "default": {              // skin
        "eye": {                // slot
          "eye-mesh": {         // attachment — must be a mesh in this skin and slot
            "deform": [ { "time": 0 }, { "time": 0.2, "vertices": [0, -4, 0, -4] } ]
          }
        }
      }
    }
  }
}

Why it happens

  • The mesh was renamed or deleted after it was animated.
  • The mesh was turned back into a region (a plain image), and the deform keys stayed.
  • The keys are under the wrong skin: the mesh lives in skin red, the deform is written under default.

How to fix it

Walk the deform path of each animation and check that the skin has a mesh attachment with that name in that slot. Rename the key to the real mesh, move it under the right skin, or delete the deform timeline. The validator below names the exact animation, slot and attachment.

Check your skeleton

The Spine JSON validator finds this in a skeleton.json before the runtime does, and names the exact place. It runs in your browser; the file is not uploaded. Riggy runs the same check on every rig it builds.

Other Spine runtime errors