Quick answer: Decide the respawn rule (on room re-entry or after a timer), hide the block instead of freeing it, and restore it when the rule is met rather than relying on re-instancing.
Some breakable blocks are one-time and some must come back so the player can re-solve a route. For respawning blocks, disable rather than destroy and restore on the chosen trigger.
How to fix it
1. Choose a respawn rule
Permanent shortcuts stay broken; puzzle or traversal blocks should respawn on room exit/re-entry or after a fixed delay. Tag each block with which behavior it uses.
2. Hide instead of free
For respawning blocks, on break set them invisible and non-colliding with a flag, instead of calling queue_free(). A freed node cannot be cheaply restored to its exact place.
3. Restore on the trigger
When the player leaves the room or the timer elapses, re-enable the block's visibility and collision. Reset any debris particles so it looks intact again on return.
Catching the ones you can't reproduce
The hardest version of this to fix is the one you can't reproduce — it only happens on a player's hardware, OS, driver, or save state, under conditions that simply aren't present on your machine. A report that says “it crashed” or “it froze” gives you nothing to act on, so the bug survives release after release while quietly costing you players.
Automatic error capture closes that gap. Each failure arrives with its full stack trace, the device and OS, the build number, and a breadcrumb trail of what the player did right before it broke, so even a failure you have never seen becomes a specific, reproducible issue. Fold identical failures into one signature ranked by how many players each hits, and your worklist sorts itself worst-first instead of arriving as a stream of vague complaints.
This is where a tool like Bugnet earns its place. Its SDK captures every Godot error automatically with the full stack trace plus device, OS, memory, build, and game-state context, folds duplicates into one grouped issue with an occurrence count, and ties each to the build it first appeared on — so you fix the problem that hurts the most players first and confirm it is gone when its signature disappears from the next release.
Ship the fix, watch the signature disappear from the next build. That's how you know it's really gone.