Plugin script: `Invalid access to property or key` (some signal) `on a base object of type Node (` (some class that DOES have that signal) `)

Godot Version

4.6

Question

(CAVEMAN SUMMARY)
error says “some_node.some_signal” does not exist. “some_node.some_signal” exists! how to make error not happen anymore?

(VIDEO DEMONSTRATION)
I’m a new user, so i can’t post videos. sorry!

(LONG STORY)
I’m writing a plugin that manipulates Skeleton3D nodes using a custom SkeletonPoser node.
The poser has signal some signal members:

(skeleton_poser.gd)

@tool
class_name SkeletonPoser extends Node
##(class code here)
...
signal pose_stack_changed

signal current pose_changed
...

And then an editor plugin connects and disconnects signals when the user selects and deselects that node, so that the UI can track whether they are editing the poser and if some property changed that requires updating buttons, lists, show popup dialogs, whatever:

(skeleton_pose_editor_menu.gd)

@tool 

class_name SkeletonPoseEditorMenu extends Control

...
...

var skeleton_poser: SkeletonPoser

...
...

# FIXME: This section is broken as hell.
# on this specific part of the script, the editor refuses to acknowledge that the 
# SkeletonPoser class has signals, and thus throws an error if you try to disconnect them.
func detach_poser():
	if self.skeleton_poser != null:
		var script_of_object: Script = skeleton_poser.get_script()
		print_debug("detaching object ", skeleton_poser, " of class: '", skeleton_poser.get_class(), "', type '", script_of_object.get_global_name(), "'")
		var signal_exists: bool = skeleton_poser.has_signal("pose_stack_changed")
		if (signal_exists):
			print_debug("this object has signal 'pose_stack_changed")
		else:
			print_debug("this object DOES NOT have signal 'pose_stack_changed")
		if skeleton_poser.pose_stack_changed.is_connected(pose_stack_dialog._redraw_pose_stack):
			self.skeleton_poser.pose_stack_changed.disconnect(pose_stack_dialog._redraw_pose_stack)
		if skeleton_poser.pose_stack_changed.is_connected(pose_stack_dialog._refresh_pose_picker):
			skeleton_poser.pose_collection.changed.disconnect(pose_stack_dialog._refresh_pose_picker)
		skeleton_poser = null
	set_process(false)
	hide()
	pass

...
...

Notice how i embedded debug statements into the troublesome code itself to study what exactly is going on.
When i deselect the skeleton poser node to focus on something else, the plugin calls edit() with a null value (as per documentation), and that leads to the above detach_poser() being called on the UI.
This generates the following output on the console output tab:

detaching object SkeletonPoser:<Node#1798953835061> of class: 'Node', type 'SkeletonPoser'
   At: res://addons/skeleton_manager_plugin/skeleton_pose_editor_menu.gd:155:detach_poser()
this object has signal 'pose_stack_changed'
   At: res://addons/skeleton_manager_plugin/skeleton_pose_editor_menu.gd:158:detach_poser()
  ERROR: res://addons/skeleton_manager_plugin/skeleton_pose_editor_menu.gd:161 - Invalid access to property or key 'pose_stack_changed' on a base object of type 'Node (SkeletonPoser)'.

The object’s script type matches, that instance does have that signal at that precise moment, so why, WHY does it throw an error when i try to disconnect, or even check if it is connected, when it is not selected on the editor?
Even more puzzling is that on the same plugin script file, there is a line:
skeleton_poser.pose_stack_changed.connect(pose_stack_dialog._redraw_pose_stack)
that works just fine. It’s the same signal, on the same member variable, it just happens that the poser is being selected on the editor.

How can i reach that pesky signal so that i can disconnect it and avoid the editor watching a node i’m not manipulating right now?

Have you tried this?

if self.skeleton_poser.pose_stack_changed

You did if in the first if statement - I assume there was a reason for that.

Smells like circular reference.

This is a leftover from when i thought the skeleton poser variable might be from some other context. It throwed the same error with or without self as a namespace specifier.

Here’s an update.
I tested other parts of the plugin, then left the computer suspended for ~6 hours and when i turned it back on and did the same steps that displayed the error (create custom node, select custom node, select any other node) it doesn’t throw the error anymore.
If this error continues NOT to happen for the next 5 days i’ll just assume something unrelated to the script itself was causing this and was fixed, and i’ll close the topic.

I tweaked a bunch of things and changed how the menus show and hide on _edit() callback, and now the error doesn’t happen anymore. closing this.