Skip to content

Heightfield collider creation crashes with RuntimeError: unreachable in WASM (rawshape_heightfield) #146

@nilssonus

Description

@nilssonus

Hello Rapier team,

I'm currently trying to develop a game using AI and rapier.js.
While working on the multiplayer feature, the AI found a bug — or at least it's convinced that it did.
It would be great if you could take a look at it. Is the AI using rapier.js incorrectly? Or is it really a bug?

Here’s the AI’s Crash Report:

Rapier.js Heightfield Crash Report

Title

Heightfield collider creation crashes with RuntimeError: unreachable in WASM (rawshape_heightfield)

Description

Creating a heightfield collider using ColliderDesc.heightfield() and then inserting it into a World via world.createCollider() crashes with RuntimeError: unreachable in the WASM code at rawshape_heightfield. This occurs in both Node.js and browser environments.

The ColliderDesc itself can be created without errors, but the crash happens when the collider is actually inserted into the physics world (during the intoRaw() conversion).

Steps to Reproduce

  1. Install @dimforge/rapier3d-compat@0.19.3
  2. Run the following minimal reproduction script:
import fs from 'node:fs';
import RAPIER from '@dimforge/rapier3d-compat';

// Sample heightfield data (129x129 grid = 16641 points)
const dump = JSON.parse(fs.readFileSync('heightfield-sample.json', 'utf8'));
const heights = Float32Array.from(dump.heights);

await RAPIER.init();
const world = new RAPIER.World({ x: 0, y: -25, z: 0 });

// This works fine - ColliderDesc creation succeeds
const desc = RAPIER.ColliderDesc.heightfield(
  dump.pointsPerAxis,  // 129
  dump.pointsPerAxis,  // 129
  heights,             // Float32Array of length 16641
  { x: 4, y: 1, z: 4 } // scale
).setFriction(1.2);

// This crashes with RuntimeError: unreachable
world.createCollider(desc);
  1. The crash occurs at the world.createCollider() call.

Expected Behavior

The heightfield collider should be created and inserted into the world without errors.

Actual Behavior

RuntimeError: unreachable
    at wasm://wasm/005fccd2:wasm-function[1156]:0x150170
    at wasm://wasm/005fccd2:wasm-function[1720]:0x169408
    at wasm://wasm/005fccd2:wasm-function[677]:0x125ed4
    at OA.heightfield (file:///.../rapier.mjs:1:65928)
    at og.intoRaw (file:///.../rapier.mjs:1:108710)
    at qg.createCollider (file:///.../rapier.mjs:1:139073)
    at ag.createCollider (file:///.../rapier.mjs:1:122196)

The crash happens in rawshape_heightfield during the intoRaw() conversion when creating the collider.

Environment

  • Package: @dimforge/rapier3d-compat@0.19.3
  • Node.js: v24.8.0
  • OS: macOS 14.6.0 (darwin 24.6.0)
  • Architecture: ARM64 (Apple Silicon)
  • Module System: ES Modules

Additional Information

Heightfield Data Details

  • Grid size: 129 × 129 points (16,641 total height values)
  • Height range: min ≈ 0.70, max ≈ 36.34
  • Scale: { x: 4, y: 1, z: 4 }
  • Data format: Float32Array with values in column-major order (as expected by Rapier)

Tested Variations

The crash occurs regardless of:

  • Using raw heights vs. normalized heights (0-1 range)
  • Different scale values (including { x: 4, y: heightRange, z: 4 })
  • Creating a new World vs. using an existing one
  • Browser environment (Vite + @dimforge/rapier3d-compat) vs. Node.js

Workaround Attempts

  • Creating the ColliderDesc without inserting it works fine
  • The same data works in other physics engines (tested with alternative implementations)
  • Smaller heightfields (e.g., 4×4) also crash with the same error

Sample Data

A complete heightfield sample data file is available at:
debug/heightfield-sample.json in this repository.

The file contains:

  • pointsPerAxis: 129
  • heights: Array of 16,641 float values
  • scale: { x: 4, y: 1, z: 4 }
  • min: 0.7003778219223022
  • max: 36.34062194824219

Related

This blocks our multiplayer terrain system, as we cannot create terrain colliders for dynamically streamed chunks. The same heightfield data works correctly when tested with other physics engines, suggesting the issue is specific to Rapier's WASM implementation.


Please let me know if you need any additional information.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions