Skip to content

createStateMachine(nil) creates zombie handle instead of default SM for artboards with named state machines #440

@cerupcat

Description

@cerupcat

Summary

When calling artboard.createStateMachine(nil) on an artboard with no state machines, the Swift layer constructs and returns a StateMachine handle backed by a null C++ object. That zombie handle gets registered in the CommandServer and produces a continuous stream of errors on every display-link frame:

ERROR : Could not create state machine with name "" because it was not found.
ERROR : State machine 0x1 not found for binding view model.
ERROR : State machine 0x1 not found for advance.

Steps to Reproduce

  1. Have a .riv file whose default artboard has zero state machines.
  2. In the async runtime, call artboard.createStateMachine() (i.e. name: nil).
  3. Pass the returned StateMachine to Rive(file:artboard:stateMachine:...).
  4. Observe continuous "State machine 0x1 not found for advance" errors on every display-link tick.

Root Cause

createStateMachine(nil) correctly routes to createDefaultStateMachine in StateMachineService (index-based via stateMachineAt(0)) — not a name-based "" lookup as the error message might suggest. The error message format just happens to say name "" even for the index-based path when it fails.

The bug is that when stateMachineAt(0) returns null (artboard has no SMs), the Swift layer does not validate this before constructing and returning a StateMachine handle. The named path already validates via getStateMachineNames() and throws ArtboardError.invalidStateMachine — the nil/default path has no equivalent null-check.

Expected Behavior

createStateMachine(nil) should throw ArtboardError.invalidStateMachine when the artboard has no state machines, consistent with how the named path handles missing SMs.

Actual Behavior

A zombie StateMachine handle is returned. No Swift error is thrown. The zombie is advanced every frame, producing continuous runtime errors until the artboard is torn down.

Suggested Fix

Add a null-check in the nil/default path — after createDefaultStateMachine resolves, validate that the resulting handle is non-null before returning. If null, throw ArtboardError.invalidStateMachine (matching the named path's error behavior).

Additional Note

This also exposes a regression in supported file configurations vs. the legacy API — see the earlier comment for details.

Environment

  • rive-ios version: 6.19+
  • Platform: iOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions