Skip to content

Export values on instances are lost when there is a parse error on project load. #938

Open
@Poikilos

Description

@Poikilos

Tested versions

System information

Windows 11 and Ubuntu Studio 24.04, tested with both Redot 4.3 and Godot 4.3 on each OS

Issue description

I get the errors and it seems to erase values of exports that I had set in the GUI, unless that is a separate issue (at some point I did cut and paste exports to the top of a file, not sure if this one, but didn't save until I pasted). For example, load this project in 4.3 (Scroll down and click "Source code" version 0.9): https://poikilos.itch.io/locktopia

  • The entire superclass (Prop in this case) is not even shown in the Inspector when selecting the subclass instance in the Scene, until the syntax error is removed from the code.

Project load errors:

Redot 4.3 on Ubuntu Studio 24.04 Redot Engine v4.3.stable.official (c) 2007-present Juan Linietsky, Ariel Manzur & Godot Contributors & Redot Contributors. --- Debug adapter server started on port 6006 --- --- GDScript language server started on port 6005 --- res://models/characters/player.gd:2 - Parse Error: Could not resolve class "Humanoid". res://craft_item.gd:-1 - Compile Error: modules/gdscript/gdscript.cpp:2938 - Failed to load script "res://craft_item.gd" with error "Parse error". (User) res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type "null" as "Vector3". res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type null to variable "move_to_vec3" with specified type Vector3. modules/gdscript/gdscript.cpp:2938 - Failed to load script "res://models/characters/prop.gd" with error "Parse error". (User) res://models/characters/destructible_prop.gd:2 - Parse Error: Could not resolve class "Prop". modules/gdscript/gdscript.cpp:2938 - Failed to load script "res://models/characters/destructible_prop.gd" with error "Parse error". (User) res://models/characters/creature.gd:2 - Parse Error: Could not resolve class "DestructibleProp". modules/gdscript/gdscript.cpp:2938 - Failed to load script "res://models/characters/creature.gd" with error "Parse error". (User) res://models/characters/humanoid.gd:2 - Parse Error: Could not resolve class "Creature". modules/gdscript/gdscript.cpp:2938 - Failed to load script "res://models/characters/humanoid.gd" with error "Parse error". (User) res://models/characters/player.gd:2 - Parse Error: Could not resolve class "Humanoid". res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type "null" as "Vector3". res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type null to variable "move_to_vec3" with specified type Vector3. res://models/characters/destructible_prop.gd:-1 - Compile Error: res://models/characters/creature.gd:-1 - Compile Error: res://models/characters/humanoid.gd:-1 - Compile Error: res://models/characters/player.gd:-1 - Compile Error: res://inventory_slot.gd:-1 - Compile Error: modules/gdscript/gdscript.cpp:2938 - Failed to load script "res://inventory_slot.gd" with error "Parse error". (User) res://narrator.gd:-1 - Compile Error: modules/gdscript/gdscript.cpp:2938 - Failed to load script "res://narrator.gd" with error "Parse error". (User) res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type "null" as "Vector3". res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type null to variable "move_to_vec3" with specified type Vector3. res://world.gd:-1 - Compile Error: modules/gdscript/gdscript.cpp:2938 - Failed to load script "res://world.gd" with error "Parse error". (User)
Godot 4.3 on Ubuntu Studio 24.04 Godot Engine v4.3.stable.official (c) 2007-present Juan Linietsky, Ariel Manzur & Godot Contributors. --- Debug adapter server started on port 6006 --- --- GDScript language server started on port 6005 --- res://models/characters/player.gd:2 - Parse Error: Could not resolve class "Humanoid". res://craft_item.gd:-1 - Compile Error: modules/gdscript/gdscript.cpp:2936 - Failed to load script "res://craft_item.gd" with error "Parse error". (User) res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type "null" as "Vector3". res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type null to variable "move_to_vec3" with specified type Vector3. modules/gdscript/gdscript.cpp:2936 - Failed to load script "res://models/characters/prop.gd" with error "Parse error". (User) res://models/characters/destructible_prop.gd:2 - Parse Error: Could not resolve class "Prop". modules/gdscript/gdscript.cpp:2936 - Failed to load script "res://models/characters/destructible_prop.gd" with error "Parse error". (User) res://models/characters/creature.gd:2 - Parse Error: Could not resolve class "DestructibleProp". modules/gdscript/gdscript.cpp:2936 - Failed to load script "res://models/characters/creature.gd" with error "Parse error". (User) res://models/characters/humanoid.gd:2 - Parse Error: Could not resolve class "Creature". modules/gdscript/gdscript.cpp:2936 - Failed to load script "res://models/characters/humanoid.gd" with error "Parse error". (User) res://models/characters/player.gd:2 - Parse Error: Could not resolve class "Humanoid". res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type "null" as "Vector3". res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type null to variable "move_to_vec3" with specified type Vector3. res://models/characters/destructible_prop.gd:-1 - Compile Error: res://models/characters/creature.gd:-1 - Compile Error: res://models/characters/humanoid.gd:-1 - Compile Error: res://models/characters/player.gd:-1 - Compile Error: res://inventory_slot.gd:-1 - Compile Error: modules/gdscript/gdscript.cpp:2936 - Failed to load script "res://inventory_slot.gd" with error "Parse error". (User) res://narrator.gd:-1 - Compile Error: modules/gdscript/gdscript.cpp:2936 - Failed to load script "res://narrator.gd" with error "Parse error". (User) res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type "null" as "Vector3". res://models/characters/prop.gd:7 - Parse Error: Cannot assign a value of type null to variable "move_to_vec3" with specified type Vector3. res://world.gd:-1 - Compile Error: modules/gdscript/gdscript.cpp:2936 - Failed to load script "res://world.gd" with error "Parse error". (User)

Even though the project works fine if you delete the bugged part: = null in prop.gd.

  • Yea, I know I really overused inheritance here. Maybe that contributes to the problem? Inheritance is Prop -> DestructibleProp -> Creature -> Humanoid -> Player
  • Many player instances are in the "Main" scene (which has world.gd attached) under the Characters node in the GUI.
  • The lost attributes are in prop.gd which is the file with the = null bug (Vector3 cannot be set to null, but my code has that, my mistake).
    • Every Player instance on the scene had every value filled in for the following exports defined in prop.gd, and every instance's values were all lost:
      • caption
      • affinity
      • motive
      • a few police officers had "move_to_vec3" set, which is actually a bugged line as I mentioned
    • Yeah, I should mention in my case the project was made in Redot 4.3, and it happened once before when loading a project in Redot 4.3, not just the (one) time I loaded it on Godot 4.3 for making a Windows build. I really don't want to boot Windows right now but I can try to open it in that for now. The log above is from Godot 4.3 on Ubuntu Studio 24.04.

Happened twice during the 2-week game jam It's Based Jam - Winter 2021. Final version had no NPC names 😢 so I started using node names for character names and parent nodes to calculate affinity and motive after that, probably from now on because I really don't want to lose that work.

Steps to reproduce

  • Make a new scene that inherits from CharacterBody3D, such as "Prop". Attach a script and add class_name Prop
    • (more levels of inheritance may be required--see issue description)
      • Make an inherited scene called "Player" using a gd script.
        • Add at least one statically typed export such as "@export var caption: String"
  • Make a 3D scene which will be the main scene called "World". Attach a script and save it as "world.tscn"
    • (This step is probably not required) Add at a Node3D such named "Characters". Add another under it called "npcs". Add another under that called "momandpopshop", and add instances below under that one.
    • Add at least one instance of the new Player scene described above to the scene.
    • Set "caption" on the instance.
  • Save. At this point, the main tscn will contain the values. Continue below to reproduce the issue.
  • Add the following additional export to the prop.gd which has a clear bug (= null not allowed on Vector3): @export var move_to_vec3: Vector3 = null
  • Save & Close Redot
  • As soon as you save, the export values are lost, as in not in the main tscn file anymore.
  • Open the project, and the errors messages appear immediately, and you'll notice the export values are no longer in the Scene tree for the world scene.

Minimal reproduction project (MRP)

Yeah sorry I'm really burned out from the game jam but will try to get around to it. Other than the large tar.gz above, the MRP is probably created using the rather quick steps to reproduce above.

If anyone can post that as an MRP I can try to help with it but just not right away. I just figured this is pretty important to get the issue started without it for now, to prevent data loss in projects, especially since the cause and solution are pretty clear.

I can't really get the issue to happen in a smaller example: issue-938-MRP-WIP.zip, only in the big one above. I can't tell what would exactly be the difference that causes the behavior.

Workaround: I mentioned, use nodes as categories and other important attributes. Parent nodes are not really a full solution as it is limited--if you need more attributes you could add child nodes (the actual node name or constants in the child would contain the value) would be the only stable way I can see to fully avoid using @export, and is unwieldy.

  • or don't leave syntax errors before closing Redot--that may avoid it as well...
  • See also the issue link on Godot 4.4 dev3 above

A quick solution would seem to be to have some sort of error message that would prevent Redot from closing in this case, such as:

"An error in %s prevents ALL exports defined there and set in the Scene tree from being saved if you close the program now." where %s is the gd filename. It seems like the best buttons for this dialog would be "Go to error", "Discard Data" and maybe the QUIT signal in linux would trigger this and only SIG_KILL (kill -9 $PID) should actually close the program without this dialog stopping the close, or maybe have a countdown in one and/or the other case.

A better solution seems to be to save the data in the editor regardless of whether it is defined anymore, since if the Inspector has a widget for it and there is data present, clearly the user wants to save the data (We can say with certainty this is the user's intention at least in the case the file merely has a bug--even if export is deleted or renamed, they may want the data back in the short or long term, not realizing it was lost). If this code is deeply intertwined with the way the engine works (such as, only properties defined are saved), maybe have a file called %s.lost+found.tscn (where %s is filename that defines the values but has a parsing error) that would contain values that were in the old file and not the new file (If writing the file, make sure to read it if it already exists so a merge can be performed before overwriting).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Open

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions