#4810·bullet3

PyBullet saveWorld resurrects a removed object after body-ID reuse

Author: peachtree0222Created Sep 15, 2026Updated Sep 15, 2026

Environment

  • OS: Ubuntu 24.04.5 LTS, Linux 7.0.0-28-generic x86_64
  • Compiler: GCC 11.5.0
  • Python: 3.12.3
  • Source: bulletphysics/bullet3 master at 63c4d67e337017f9d8b298c900e9aabdb69296e7
  • PyBullet: built locally from that exact checkout

Description

PyBullet records imported filenames and body IDs in m_saveWorldBodyData. removeBody frees the body handle but leaves its ID in that serialization metadata. When a later object reuses the ID, saveWorld resolves the stale record through the replacement and serializes both assets at the replacement's pose.

Expected behavior: saveWorld emits only objects that are live at save time.

Actual behavior: the reproducer loads cube.urdf as body 0, removes it, and loads sphere2.urdf at x=5 as reused body 0. The saved program contains both a cube load and a sphere load, each at x=5. Replaying it therefore resurrects the deleted cube.

Sources:

Reproduction package:

save-world-removed-body-id-poc.zip

Steps to reproduce

  1. Build PyBullet from the commit above using poc/README.md.
  2. Run python poc/reproducer.py.
  3. Inspect the printed loadURDF lines and the generated saved_world.py.

Observed output is in poc/observed-output.txt.