fix: guard moonraker None deref in in_print_reactor_timer#703
Conversation
If PREP has not been run, self.moonraker is None. The reactor timer in_print_reactor_timer would then call self.moonraker.get_file_filament_change_count on a NoneType, raising AttributeError and crashing klipper. Add a None check on self.moonraker alongside the in_print check, matching the existing pattern at the td1_present property (line ~516). Fixes AFCProject#702 Signed-off-by: SAY-5 <say.apm35@gmail.com>
|
@SAY-5 I don't disagree with this change, but are you running AFC with the PREP delayed gcode commented out? PREP should ALWAYS run upon starting/restarting klipper since this sets the initial state of all lanes and other things. I am just curious on how you are running AFC if PREP is not being ran, or is it AFC fails to connect to moonraker sometimes? Edit: Just noticed this fixes an issue, maybe you are just addressing this :-) |
|
Glad you got it sorted! Anything else surfacing? |
There was a problem hiding this comment.
Pull request overview
This PR fixes a crash in extras/AFC.py where in_print_reactor_timer could dereference self.moonraker when it is None (e.g., when PREP hasn’t been run), matching the existing guard style used elsewhere (like td1_present). It also adds focused unit tests to reproduce the failure and validate the guarded behavior.
Changes:
- Add a
self.moonraker is not Noneguard to preventNoneTypedereference inin_print_reactor_timer. - Add unit tests covering: moonraker
Nonecase, happy path with moonraker set, and not-in-print path.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
extras/AFC.py |
Guards Moonraker access in in_print_reactor_timer to prevent crashes when Moonraker isn’t initialized. |
tests/test_AFC.py |
Adds regression and behavior tests around in_print_reactor_timer Moonraker guarding. |
Comments suppressed due to low confidence (1)
extras/AFC.py:554
- The new guard
if in_print and self.moonraker is not None:now skips the entire block when Moonraker isn’t initialized. That block also updates the current lane’s buffer error position (used to avoid false-positive fault detection), which previously ran wheneverin_printwas true. To avoid an unintended behavior change, consider keepingif in_print:for the lane/buffer update and only guarding the Moonraker metadata lookup (and any variables that strictly depend on it) withself.moonraker is not None.
if in_print and self.moonraker is not None:
# Gather file filament change count from moonraker
self.number_of_toolchanges = self.moonraker.get_file_filament_change_count(print_filename)
self.current_toolchange = -1 # Reset
self.logger.info("Total number of toolchanges set to {}".format(self.number_of_toolchanges))
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Major Changes in this PR
Fixes #702. If PREP is not run,
self.moonrakerisNone. The reactor timerin_print_reactor_timerthen callsself.moonraker.get_file_filament_change_count(print_filename)onNoneType, raisingAttributeErrorand crashing klipper:Adds a
self.moonraker is not Nonecheck alongside the existingin_printcheck, matching the same guard pattern already in use for thetd1_presentproperty.Notes to Code Reviewers
The fix is a single conjunct added to the
if in_print:condition atextras/AFC.py:552(DEV branch). Same pattern astd1_present(around line 516) which already gates moonraker access onself.moonraker is not None.How the changes in this PR are tested
Three unit tests added to
tests/test_AFC.py(TestInPrintReactorTimer):test_skips_moonraker_call_when_moonraker_is_none, reproduces the crash; passes after fix.test_calls_moonraker_when_in_print_and_moonraker_set, happy path.test_does_not_call_moonraker_when_not_in_print, pre-existing not-in-print path.Full suite:
1165 passed in 1.95s.PR Checklist: (Checked-off items are either done or do not apply to this PR)