Cannot understand 'nonexistent signal' error

Godot Version

v4.6.2

Question

Hi, I’m trying to figure out why this error keeps being thrown on my character select screen once you press start. Here’s the error code:

character_selection.gd:16 @ _on_start_button_pressed(): In Object of type 'Area2D': Attempt to connect nonexistent signal 'ate_food' to callable 'Area2D(Strawberry)::_on_ate_food'.

  <C++ Error>   Condition "!signal_is_valid" is true. Returning: ERR_INVALID_PARAMETER
  <C++ Source>  core/object/object.cpp:1638 @ connect()
  <Stack Trace> character_selection.gd:16 @ _on_start_button_pressed()

This error only happens right after I press start(clearly) and I don’t know if it’s because I need to fix something regarding my signals or if it’s something to do with how I’m loading the next scene?

The ‘ate_food’ signal is in my SignalBus script and the Area2D Strawberry is just a strawberry that’s been loaded into the scene - which, when it’s been eaten/interacted with, is supposed to emit the ‘ate_food’ signal to whoever eats it.

Here’s my character_selection script:

extends Control
@onready var characer_selection_box: Control = $Container

func _on_choose_rabbit_pressed() -> void:
	Global.selected_character = 1

func _on_choose_fox_pressed() -> void:
	Global.selected_character = 2

func _on_start_button_pressed() -> void:
	get_tree().change_scene_to_file("res://testmap.tscn")

If I need to show the strawberry code, I can, but really all it’s doing is emitting a value to the global signalbus.

Is the strawberry being loaded into the scene when the node requiring it is at the same time the that node is loaded? I may need more context, but based off of what you said so far, it seems that there is an invalid signal due to the lack of the instance required loaded in the scene at the same time as the node expecting the signal. I would assume this is correct, but I am not 100% sure.

So I did a bit of testing and here’s what I came up with. I have a script on my World node that loads in whatever the selected character is.

Here’s the world script in case it’s needed:

var player_scene


func _ready():
	
	if Global.selected_character == 1: #rabbit
		print("Rabbit selected~")
		player_scene = load("res://scenes/entities/player/player_rabbit.tscn").instantiate()
		add_child(player_scene)
	elif Global.selected_character == 2: #fox
		player_scene = load("res://scenes/entities/player/player_fox.tscn").instantiate()
		add_child(player_scene)
	
	player_scene.position = player_spawn_point.global_position

In the same area it loaded in the character, I had it print before that. I did the same thing for the Strawberry and the Strawberry prints that it’s ready before the character when I load up the scene.

However, I can take all the stuff mentioning the ate_food signal out of the player script and I still get the same error.

Here’s my ‘SignalBus’ script:

extends Node

signal ate_food(amount:int) #to communicate food has been eaten
signal player_interaction(bool)

I don’t know if letting the scene load in first or something will fix it but I’m confused why it’s not recognizing a global signal.

Since the strawberry is the one that’s supposed to emit the signal, it would be helpful to see its code even if it’s short.

Okay, strawberry code below:

class_name Strawberry extends Area2D
@export var type := "Berry"
var food_amount := 20 #how much food it gives
var animal_in_area := false #so you can't eat across the map / from anywhere
#var eatable = false
func _ready() -> void:
	print("strawberry loaded.")

func _process(_delta: float) -> void:
	#print(signal_check)
	if animal_in_area == false:
		return
	elif animal_in_area == true:
		#eatable == true
		#not sure how to have npc animal eat object but we'll see
		if Input.is_action_just_pressed("interact"):
			if Messenger.has_signal("ate_food"):
				eaten()
				print("signal readY")
			##Messenger.connect("ate_food(20)")
			#Messenger.ate_food.emit(food_amount)
			else:
				return

func _on_area_entered(_area: Area2D) -> void:
	animal_in_area = true
	print("animal in area!")
	#if eaten = stop existing
	#have a game manager create more?

func _on_area_exited(_area: Area2D) -> void:
	animal_in_area = true
	print("animal left")


func eaten():
	Messenger.ate_food.emit(food_amount)
	queue_free()

It might be a mess from me trying to rework it for hours today

I’m a bit confused. I cannot find the ‘on ate food’ function in Strawberry. Also, you cannot pass values in the connection. Other things in the syntax is also off. Normally you go Messenger.my_signal.connect(my_function)

##Messenger.connect(“ate_food(20)”)

Is the connection done elsewhere and you weren’t using this code since it’s commented out. Can you show the actual connection line?

I would assume this

OK, is there any info missing? what does the console say when you run the code?

No i meant the connection itself. Not emitting. I also cannot find the ‘on ate food’ that the errors were talking about.

perhaps it is located inside the check collision work node’s script.

Sorry, yeah I tried a bunch of things over the hours so some things got replaced and mixed up. Nothing seemed to work. I comment over any code that I think I might need to reuse since I’m still learning and it’s sometimes hard for me to remember how exactly to write certain things.

Here’s what I originally had:

if Input.is_action_just_pressed("interact"):
			_on_ate_food()

Then here’s the _on_ate_food function:

func _on_ate_food() -> void: #tell whoever ate me that they did and then disappear
	Messenger.ate_food.emit(food_amount)
	print("eaten")
	queue_free()

As for the connection, I have a connection setup in the player’s hunger component, and it’s been successful at receiving the food value, even though I keep getting the error as soon as I load into the game.

Here’s the function in the player’s hunger component that I call at _ready to check for a signal:

func signal_check():
	if Messenger.connect("ate_food", add_hunger): #if Messenger.ate_food.connect(add_hunger):
		return
	else:
		return

Here’s the full thing for the error (total of 3) (sorry I didn’t think these had anything to do with it). These show up in yellow/tan:

W 0:00:00:416   GDScript::reload: The signal "ate_food" is declared but never explicitly used in the class.
  <GDScript Error>UNUSED_SIGNAL
  <GDScript Source>messenger.gd:3 @ GDScript::reload()

W 0:00:00:416   GDScript::reload: The signal "player_interaction" is declared but never explicitly used in the class.
  <GDScript Error>UNUSED_SIGNAL
  <GDScript Source>messenger.gd:4 @ GDScript::reload()

And the error I sent earlier (red):

E 0:00:02:791   character_selection.gd:11 @ _on_start_button_pressed(): In Object of type 'Area2D': Attempt to connect nonexistent signal 'ate_food' to callable 'Area2D(Strawberry)::_on_ate_food'.
  <C++ Error>   Condition "!signal_is_valid" is true. Returning: ERR_INVALID_PARAMETER
  <C++ Source>  core/object/object.cpp:1638 @ connect()
  <Stack Trace> character_selection.gd:11 @ _on_start_button_pressed()

OK, well first of all, I will say that the _on_ate_food() function’s indentation seems to be unaligned with the Input.is_action_just_pressed condition.

What does the character_selection.gd look like?
It says that on line 11 there is an issue at the _on_start_button_pressed() function. it says that it is trying to connect a signal that doesnt exist to the strawberry…

With the full character_selection and strawberry scripts i should be able to point out the issue.
(strawberry already uploaded)

The character_select.gd is in the first post but I’ll paste it down here for easy reading!

extends Control
@onready var characer_selection_box: Control = $Container

func _on_choose_rabbit_pressed() -> void:
	Global.selected_character = 1

func _on_choose_fox_pressed() -> void:
	Global.selected_character = 2

func _on_start_button_pressed() -> void:
	get_tree().change_scene_to_file("res://testmap.tscn")

I think it might have something to do with load order, since the strawberry is printing that it’s ready before other things (like character’s being loaded in) but I don’t know how I would fix that.

Can you write a short summary of what is actually going on in terms of signals and the order of loading in or gameplay as you understand it? No need the actual code, just in plain english what event happens after what. I’m not too familiar with this genre of animal game unfortunately.

Also, i don’t think process is a common place for these input checks. Usually you put it in unhandled key input function or some other such function so it doesn’t keep running all the time.

I see… so that is the full file… Now, earlier with the yellow errors, I realized that they are actually critical to the solution.

I earlier suspected it was an order issue, try a test by commenting out some files and see which logical combination eliminates the error, that will tell us where the problem lies.

Yes, 100%.

My main scene the game starts on is a main menu. You click start and the scene changes to character select. In the character select you click on one of the species (only really trying to get one, the rabbit, up and working right now) and each are assigned a variable(established in global) that represents them. That info is read by the world(testmap) script and spawns in whichever animal chosen when you load the scene. Still in character select, you press the start button (the very one that the original error i sent in stems from), which loads the scene (testmap is what it’s called rn).

When test map is loaded in, Strawberry is loaded with it and the signal on it is only emitted when something enters the area and interacts with it.

Meanwhile, I have a ‘SignalBus’ script thats loaded as a global, establishing the ‘ate_food’ signal because later I want not just the player (but other NPC’s) to be able to trigger that signal - otherwise I would just connect this straight to the player.

That’s the best I can explain it to my understanding, sorry if it’s confusing.

Why not just make it so that it uses the same character object but with different animations and abilities depending on the ID, that would save you a lot of trouble believe me :sweat_smile:

And as for the strawberry, why not make it so that the node checks for the collision of a character and go from there? Any other signals can be done with a simple if collide == true && eat == true

Your SignalBus is called Messenger? And your Strawberry is connected using inspector to its own on_ate_food when someone is near? And you can also press interact to ‘eat’ the strawberry? And this interact button is the same one that you press to select a character?

And immediately on choosing a character, you get errors?