Skip to content

State machine not working

The animation plays, but it does not react to hover, click, or your code. Or stateMachineInputs(...) is empty.

Use this when

  • The animation loads but interactions do nothing.
  • r.stateMachineInputs("...") returns [].
  • A click on the animation visually animates, but your onRiveEventReceived handler never fires.
  • Switching stateMachines value in code has no effect.

What you need

  • DevTools console.
  • The handoff.md from Lupian (it lists artboard, state machine, input, and event names).

Run through this in order

1. Check the state machine name

The most common cause. Names are case-sensitive and must match the .riv file exactly.

js
// From handoff.md: state machine is "State Machine 1"

stateMachines: "state machine 1",  // WRONG — wrong case
stateMachines: "State Machine 1",  // RIGHT
stateMachines: "StateMachine1",    // WRONG — different name

Verify by logging:

js
new Rive({
  src: "/animations/hero.riv",
  canvas,
  autoplay: true,
  onLoad: () => {
    console.log("state machine names:", r.stateMachineNames);
  },
});

The console output is the source of truth — that is what is actually in the .riv. Use those names.

2. Did you read inputs after onLoad?

stateMachineInputs(...) returns an empty array before the file is loaded.

js
// WRONG — reads too early
const r = new Rive({ src: "...", canvas, stateMachines: "SM 1" });
const inputs = r.stateMachineInputs("SM 1"); // []

// RIGHT
const r = new Rive({
  src: "...",
  canvas,
  autoplay: true,
  stateMachines: "SM 1",
  onLoad: () => {
    const inputs = r.stateMachineInputs("SM 1");
    // ...
  },
});

In React, this is handled by useStateMachineInput(rive, "SM 1", "name"). Just make sure rive is not null when you read it (it is null on the first render).

3. Is the input name and type right?

Three input types — using the wrong one for the right name silently does nothing.

TypeHow to drive it
booleaninput.value = true / false
numberinput.value = 42
triggerinput.fire()
js
const inputs = r.stateMachineInputs("SM 1");
console.log(inputs.map(i => ({ name: i.name, type: i.type })));
// [{name: "isHovering", type: 59}, {name: "onClick", type: 58}, ...]

Compare to handoff.md. If the types do not match what you expected, the animation will appear unresponsive when you call the wrong API.

4. Wrong artboard?

A .riv file can have multiple artboards. If you do not pass artboard, the default artboard is used (set by Lupian in the editor). If you need a specific one:

js
new Rive({
  src: "/animations/hero.riv",
  canvas,
  autoplay: true,
  artboard: "Mobile",                   // from handoff.md
  stateMachines: "State Machine 1",
});

If you ask for an artboard that does not exist, the file effectively does not load.

5. Events not firing?

Make sure:

  • onRiveEventReceived is set on the Rive constructor (or as a prop on useRive).
  • The event name in your if matches exactly: event.data.name === "submitClicked".
  • The animation is actually reaching the keyframe that fires the event (test by triggering it manually if there is a trigger input that leads there).
js
new Rive({
  // ...
  onRiveEventReceived: (event) => {
    console.log("Rive event:", event.data.name, event.data);
  },
});

If this logs nothing on the action that should fire the event, the issue is in the .riv (event not wired to that state transition) — that is a Lupian-side fix. Send a clip.

6. Pointer-driven inputs (hover/click) inside the canvas

Some Rive interactions use internal pointer listeners — the animation has built-in hover/click hotspots set in the editor.

  • Make sure the canvas has pointer-events: auto and touch-action: none.
  • Make sure no element overlays the canvas (DevTools → Elements → hover canvas → check stacking).
  • In Framer especially, layers can intercept input — see Framer recipe.

Common mistakes

  • Wrong case in state machine, artboard, or input names.
  • Reading inputs before onLoad. Empty array, then silent failure.
  • Mixing .value = ... with trigger inputs, or .fire() with boolean inputs.
  • Forgetting to pass stateMachines: "..." to new Rive(...). The animation will play the default timeline but not enter the state machine at all.
  • Asking for a non-existent artboard. Misspelled artboard name → file effectively does not load.

If stuck, send this to Lupian

  • The console output of r.stateMachineNames and r.stateMachineInputs("...").map(i => i.name + ":" + i.type).
  • A clip of what is happening and what should happen.
  • Your snippet of the input/event wiring code.
  • See Ask Lupian for help.

Developer support for Lupian-delivered Rive animations