Invalid get index 'filename' (on base: 'Dictionary').

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By DDBY

Hello, I have been trying to implement a system that saves the highscore of my project (based on a tutorial), but when I finish implementing the code it gives me the following error

this is the save system script

extends Node

var save_filename = "user://save_game.save"

func _ready():
	load_game()

func save_game():
	var save_file = File.new()
	save_file.open(save_filename, File.WRITE)

	var saved_nodes = get_tree().get_nodes_in_group("Mundo")

	for node in saved_nodes:
		if node.filename.empty():
			break

		var node_details = node.get_save_stats()
		save_file.store_line(to_json(node_details))


	save_file.close()





func load_game():
	var save_file = File.new()
	
	if not save_file.file_exists(save_filename):
		return
	
	var saved_nodes = get_tree().get_nodes_in_group("Mundo")
	
	for node in saved_nodes:
		node.queue_free()
	
	
	save_file.open(save_filename, File.READ)
	
	while save_file.get_position() < save_file.get_len():
		var node_data = parse_json(save_file.get_line())
		var new_obj = load(node_data.filename).instance()
		
		get_node(node_data.parent).call_deferred("add_child", new_obj)
		
		new_obj.load_save_stats(node_data)

func _notification(what):
	if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
		save_game()

And this is the script of the node that contains the highscore

extends Node
export(PackedScene) var Roca
var Score
var Highscore = 0

onready var InicioT = $InicioTimer
onready var Interfaz = $Interfaz
onready var ScoreT = $ScoreTimer
onready var RocaT = $RocaTimer
onready var Player = $Player
onready var InicioPos = $PosiciondeInicio
onready var CaminoRP = $Camino/RocaPosicion

func _ready():
	randomize()
	
func get_save_stats():
	return{
		'stats':{
			'Hi' : Highscore
		}
	}
	
func load_save_stats(stats):
	Highscore = stats.stats.Hi
	
	
func nuevo_juego():
	Score = 0

	InicioT.start()
	Interfaz.mostrar_mensaje("Listo!")
	Interfaz.update_score(Score)
	Interfaz.update_highscore(Highscore)
	

func game_over():
	ScoreT.stop()
	RocaT.stop()
	Interfaz .game_over()
	if Highscore <= Score:
		Highscore = Score
		Interfaz.update_highscore(Highscore)
	


func _on_InicioTimer_timeout():
	RocaT.start()
	Player.inicio(InicioPos.position)
	ScoreT.start()


func _on_ScoreTimer_timeout():
	Score += 1
	Interfaz.update_score(Score)

func _on_RocaTimer_timeout():
	#Seleccionar un lugar aleatorio
	CaminoRP.set_offset(randi())
	
	var R = Roca.instance()
	add_child(R)
	
	#Seleccionar una direccion
	var d = CaminoRP.rotation + PI /2
	
	R.position = CaminoRP.position
	
	d += rand_range(-PI /4, PI /4)
	R.rotation = d
	R.set_linear_velocity(Vector2(rand_range(R.velocidad_min, R.velocidad_max), 0).rotated(d))

The only functions that contain any reference to the save script are:
func load_save_stats(stats):
func get_save_stats():

I’m really just learning to program in Gdscript and I don’t understand the error

The error is in “while save_file.get_position() < save_file.get_len():”

In the posted code, I assume the problem is here:

var new_obj = load(node_data.filename).instance()

Basically, the error means the your Dictionary (node_data here) doesn’t contain a key named filename. You can probably easily verify that with some print() statements or with some debugger break-points.

jgodfrey | 2023-02-10 16:45

Ok, if I understand, and correct me if I don’t, the only part where there is a reference to “any.filename” is in the for iteration of the save_game() function.

for node in saved_nodes:
    if node.filename.empty():
        break

I have added a print just in this iteration and at no time was the iteration seen in the debugger… I really don’t know if it is because the save_game() function is performed when the window is closed, and therefore it is not printed

DDBY | 2023-02-10 17:20

There are 2 references to <something>.filename in the posted code - the one I noted and the one you noted. I suspect the problem is in the one I noted above However, when you get the error from Godot, it’ll point you to the specific line of code with the problem.

Regardless, the problem is that the Dictionary that’s being referenced does not have a key named filename (that’s what the error text says specifically). That’s what you need to look into…

jgodfrey | 2023-02-10 17:26

I already found what the error referred to…

As you explained to me, the error was in the dictionary that did not contain filename, the only thing I did was add it and that’s it, the saving system already works :)… Really, thank you very much

 func get_save_stats():
	return{
		'filename' : get_filename(),
		'parent' : get_parent().get_path(),
		'stats':{
			'Hi' : Highscore
		}
	}

DDBY | 2023-02-10 17:58

:bust_in_silhouette: Reply From: jgodfrey

As noted in the above discussion, the resolution was to add the expectedfilename key to the Dictionary in question.