why do i get"Invalid operands 'Vector2' and 'Nil' in operator '*'." on one scene but if i recreate the scene exactly i dont get it in the new, identical one?

Godot Version

4.7.2

Question

exactly as the title:

why do I get this error, "Invalid operands 'Vector2' and 'Nil' in operator '\*'." in one scene but not in the EXACT duplicate of it?

I am following the godot documents tutorial" “Your first 2d game” to re familiarize myself with programming. My code was working perfectly fine until i decided i wanted to add a way to slow down the players movement when you hit shift, and return it to the default value when released. as soon as I added this i began getting the error “Invalid operands ‘Vector2’ and ‘Nil’ in operator ‘*’.” at this function:

if velocity.length() > 0:
velocity = velocity.normalized() * speed
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()

specifically at the line:

velocity = velcotiy.normalized() * speed

I thought maybe it was the new code i added, which boiled down to adding a variable called “speed_old” that recorded the contents of “speed” and these lines of code:

if Input.is_action_just_pressed(“slow”):
speed *= .5
print(speed) #this was just so i could make sure it was changing speed
if Input.is_action_just_released(“slow”):
speed = speed_old

so i commented out the code, then the code and “speed_old” variable, and then finally decided to copy and paste the exact code from the tutorial into my script so i knew for a fact that it was “correct” and no matter what I still kept (and keep getting) the error. essentially it went from working to not for no obvious (to me) reason

the odd thing is that i made an identical scene to the original, nodes scripts and all and its the EXACT same code but now im not getting the error and my code slowing down the player works just as intended. Is this a common bug with godot and is there a way from preventing it in the future? Id like to avoid it if possible on future projects as remaking scenes. Id also like to note that i did update from 4.6 to 4.7 mid project. but after updating to 4.7 everything still worked as intended, it only had stopped after adding code to slow the player

This is not a bug, you most likely incorrectly defined a speed or speed_old variable. Please paste the whole script.

Check Posting guidelines in #Help channel to see how to properly format your code.

this is the entire original script (please ignore the comments just me piecing things together ha ha):

extends Area2D

signal hit

@export var speed = 400.0
var speed_old = speed
var screen_size 

#setting up a function to call when restarting.  resets position, shows player and enables collision
func start(pos):
	position = pos
	show()
	$CollisionShape2D.disabled = false

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	screen_size = get_viewport_rect().size
	hide()
	pass
	
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	var velocity = Vector2.ZERO # the player's movement vector
	
#affects speed of player	
	if Input.is_action_just_pressed("slow"):
		speed *= .5
		print(speed)
	if Input.is_action_just_released("slow"):
		speed = speed_old
#movement based on input		
	if Input.is_action_pressed("move_right"):
		velocity.x += 1
	if Input.is_action_pressed("move_left"):
		velocity.x -= 1
	if Input.is_action_pressed("move_down"):
		velocity.y += 1
	if Input.is_action_pressed("move_up"):
		velocity.y -= 1

	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()
	else:
		$AnimatedSprite2D.stop()
	#this updates the players position thru built in property that defines
	#on screen position of current node, this case being the player. 
	# so we're updating the players position by multiplying the steps(which we defined in 
	# is action pressed) and time which is delta and adding that to the position which moves
	# our character
	# and since its in _process it moves along with you input cause process delta is called
	# every frame!
	position += velocity * delta
	#this clamps the position to onscreen so the player cant run off off screen
	position = position.clamp(Vector2.ZERO, screen_size)
	
	if velocity.x != 0:
		$AnimatedSprite2D.animation = "walk"
		$AnimatedSprite2D.flip_v = false
		$AnimatedSprite2D.flip_h = velocity.x<0
	elif velocity.y != 0:
		$AnimatedSprite2D.animation = "up"
		$AnimatedSprite2D.flip_v = velocity.y > 0


func _on_body_entered(body: Node2D) -> void:
	hide() #hides the players bhody
	hit.emit()#plays our signal we defined at the top "hit" and other nodes can act accordingly to this signal
	$CollisionShape2D.set_deferred("disabled", true) #disables the collision so it only happens once and not repeatedly "hit"
	

if you were to run this you would have to get rid of hide() in _ready. This was in my original player.tscn scene before I deleted it and its original script from my project(luckily it was in my trash) like I mentioned i copy and pasted this script(minus the hide function) into a new scene and thats when it started working fine again. (and yes I did remove the hide function when testing out the error in the code just to get that out of the way, it wasn’t an issue of the player not being there but my game crashing every time the player tried to move with the aforementioned error)

“new” script:

extends Area2D

signal hit

@export var speed = 400.0
var speed_old = speed
var screen_size 

#setting up a function to call when restarting.  resets position, shows player and enables collision
func start(pos):
	position = pos
	show()
	$CollisionShape2D.disabled = false

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	screen_size = get_viewport_rect().size
	
	
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	var velocity = Vector2.ZERO # the player's movement vector
	
#affects speed of player	
	if Input.is_action_just_pressed("slow"):
		speed *= .5
		print(speed)
	if Input.is_action_just_released("slow"):
		speed = speed_old
#movement based on input		
	if Input.is_action_pressed("move_right"):
		velocity.x += 1
	if Input.is_action_pressed("move_left"):
		velocity.x -= 1
	if Input.is_action_pressed("move_down"):
		velocity.y += 1
	if Input.is_action_pressed("move_up"):
		velocity.y -= 1

	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()
	else:
		$AnimatedSprite2D.stop()
	#this updates the players position thru built in property that defines
	#on screen position of current node, this case being the player. 
	# so we're updating the players position by multiplying the steps(which we defined in 
	# is action pressed) and time which is delta and adding that to the position which moves
	# our character
	# and since its in _process it moves along with you input cause process delta is called
	# every frame!
	position += velocity * delta
	#this clamps the position to onscreen so the player cant run off off screen
	position = position.clamp(Vector2.ZERO, screen_size)
	
	if velocity.x != 0:
		$AnimatedSprite2D.animation = "walk"
		$AnimatedSprite2D.flip_v = false
		$AnimatedSprite2D.flip_h = velocity.x<0
	elif velocity.y != 0:
		$AnimatedSprite2D.animation = "up"
		$AnimatedSprite2D.flip_v = velocity.y > 0


func _on_body_entered(body: Node2D) -> void:
	hide() #hides the players bhody
	hit.emit()#plays our signal we defined at the top "hit" and other nodes can act accordingly to this signal
	$CollisionShape2D.set_deferred("disabled", true) #disables the collision so it only happens once and not repeatedly "hit"
	

as you can see they are copy and pasted from one to the other. whats even more odd is since i removed the original file from the project and reintroduced it, it’s now working completely as intended.

the code was already working matter of fact all of the gameplay was done and working as intended and I was about to move on to the “UI” section of the tutorial before I decided I wanted to add a way to slow down

Im just curious as to why this happend as I mentioned before nothing about the code changed besides me adding the lines to move slower, which is working code. it kinda baffles me how it went from

working → literally no matter what i did would prevent me from getting the error at “velocity = velcotiy.normalized() * speed” → exact same code working in a different script file → exact same code working in the SAME FILE only after it was removed and reintroduced

also worth mentioning i found this post with a similar problem but the solution wasn’t relevant to my case since at no point until after the code broke did i comment out anything and that was only the lines I added for slowing down the player, which i reversed when i saw that deleting the new code did not fix the error.

sorry if this sounds crazed lol it just intrigues me but i dont know enough about game engines and such to identify if there was a problem or a one in a million atom aligned in my ram or some bs and decided to torment me for 2 hours

Sometimes export variables do get reset, if you haven’t given them a type they could be assigned to null. I would try re-assigning the speed property in your inspector, and giving it a type to be extra safe. I think this happens when changing the variable name and allowing the scene to save? If I’m correct, It’s an engine bug to some degree, but easy for users to fix and difficult for developers to solve.

@export var speed: float = 400.0