From 86e01dba16078628cde25f660ba155f0d43e6e9f Mon Sep 17 00:00:00 2001 From: "sentry[bot]" <39604003+sentry[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 10:35:38 +0000 Subject: [PATCH] Fix Moved() null.source_atom crash (#22537) * Please describe the intent of your changes in a clear fashion. This PR addresses the runtime error "Cannot read null.source_atom: proc name: Moved" occurring in `/atom/movable/proc/Moved`. **Root Cause:** When a `datum/dynamic_light_source` or `datum/static_light_source` is deleted (e.g., an item emitting light is removed), BYOND nullifies its reference in any lists it's part of. If the cleanup in the light source's `Destroy()` proc is incomplete (e.g., due to `contained_atom` changing before deletion), a null entry can remain in the `hybrid_light_sources` or `static_light_sources` lists of the atom it was attached to (like a mob). When the atom moves, the `Moved()` proc iterates these lists. Encountering a null entry and attempting to access `null.source_atom` results in a crash. **Solution:** 1. **Null-guard datum references:** Added checks (`if(!light)` and `if(!L)`) within the `Moved()` proc's loops for `hybrid_light_sources` and `static_light_sources`. 2. **Prune stale entries:** If a null datum is found, it is immediately removed from its respective list using `LAZYREMOVE` to prevent future occurrences and clean up the list. 3. **Null-guard `source_atom`:** Added a secondary check (`if(!light.source_atom)`) to ensure `source_atom` itself is not null before attempting to call `update_light()` or `static_update_light()`. These changes prevent the crash by safely handling null references during iteration and proactively cleaning up the lists. * Please make sure that, in the case of mapping changes, you include images of these changes in the PR's description. * Please make sure to mark your PR as wip or review required by making a comment with !wip or !review required * If you include sprites/sounds/... (assets) that you have not created yourself specify the license and original author below. * Ensure that you also credit them in the appropriate location / changelog as specified in the contributor guidelines ### Asset Licenses The following assets that **have not** been created by myself are included in this PR: | Path | Original Author | License | | --- | --- | --- | | icons/example.dmi | ExamplePerson (Example Station) | CC0 | Fixes SERVER-PROD-GQ --------- Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com> Co-authored-by: VMSolidus --- code/game/atoms_movable.dm | 10 +++++++++- html/changelogs/hellfirejag-dynamic-light-runtime.yml | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 html/changelogs/hellfirejag-dynamic-light-runtime.yml diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 8332eef368b..681524ddcc3 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -577,11 +577,19 @@ /* END Spatial grid stuffs */ for(var/datum/dynamic_light_source/light as anything in hybrid_light_sources) + if(!light) // datum was deleted but list entry not yet pruned + LAZYREMOVE(hybrid_light_sources, light) + continue + if(!light.source_atom) + continue light.source_atom.update_light() if(!isturf(loc)) light.find_containing_atom() for(var/datum/static_light_source/L as anything in static_light_sources) // Cycle through the light sources on this atom and tell them to update. - L.source_atom.static_update_light() + if(!L) // datum was deleted but list entry not yet pruned + LAZYREMOVE(static_light_sources, L) + continue + L.source_atom?.static_update_light() /atom/movable/Exited(atom/movable/gone, direction) . = ..() diff --git a/html/changelogs/hellfirejag-dynamic-light-runtime.yml b/html/changelogs/hellfirejag-dynamic-light-runtime.yml new file mode 100644 index 00000000000..81ef6582cc2 --- /dev/null +++ b/html/changelogs/hellfirejag-dynamic-light-runtime.yml @@ -0,0 +1,4 @@ +author: Hellfirejag +delete-after: True +changes: + - bugfix: "Fixed a runtime regularly caused by flashlights."