Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error-handling mechanism (i.e. lack of exceptions/try/catch) in GDScript is badly documented #10542

Open
geekley opened this issue Jan 22, 2025 · 1 comment
Labels
area:class reference Issues and PRs about the class reference, which should be addressed on the Godot engine repository area:manual Issues and PRs related to the Manual/Tutorials section of the documentation content:new page Issues and PRs related to creation of new documentation pages for new or undocumented features enhancement topic:gdscript

Comments

@geekley
Copy link

geekley commented Jan 22, 2025

Your Godot version: v4.3.stable.flathub [77dcf97d8]

Issue description:
Although there are requests asking for GDScript to have a sort of Exception/try/catch mechanism, it has been denied:
godotengine/godot#3516 (comment)

Exceptions won't happen. Godot is designed for things to keep working even if state is inconsistent, while at the same time reporting errors

Ok. Fine. I imagine there's a very good reason for it, so I won't go into whether or not I like this decision. I can see its point when the priority is efficiency.

But whatever is the alternative behavior is badly (euphemism to nearly-not-at-all) documented.
Firstly, there are methods that return Error, but there's quite some badly documented, e.g.:

  • Packed arrays return bool or int with no explanation of what that is, e.g. append, resize. Please have in mind that the meaning of return values is very often not obvious!
  • Signal/method connect, Array append, and many others being int instead of Error. If the int represents Error, why not fix the API? Isn't it compatible anyway, since it's an enum? Proper API is much better than having to read doc comments, because it's automatically checked and you get warnings appropriate to the expected fix. I assume it should be a non-breaking change, sorry if I misunderstand.

Anyway, this isn't even the main issue.
What is really missing is the other cases, where it's not a Error return. The "intrinsic" errors (or whatever you call these).
E.g. what happens on:

  • index-out-of-bounds error
  • null-reference error
  • invalid-cast error
  • etc

The docs for Array for example only say it pauses the project on the editor, but doesn't say what happens on runtime or when continuing:

Accessing an array out-of-bounds will cause a run-time error, pausing the project execution if run from the editor.

And the editor debugger won't let me use "step into/over" to see what happens either, I can only use "continue". Why??

Just saying "it's designed to continue" without giving specifics is far from enough. Because there's many possible interpretations:

  • Does it return null|zero|false|default (get) or ignore (set) and proceed normally?
  • Does it abort the current method only but continue from the caller, for some reason? How deep?
  • Does it abort the current frame/signal (ready/process/etc) only and proceed to next iteration?
  • Does it crash the entire game?

Imagine my surprise when I found out which one it is... (at least on the editor).
I bet most devs cannot guess what this is going to print!

@tool
extends EditorScript

func _run() -> void:
	foo()
	pass

var array: Array[Object] = []
func foo() -> void:
	bar('A')
	bar('B')

func bar(p: String) -> void:
	for i: int in range(3):
		prints(p, i, 'before')
		prints(p, i, 'get', array[i]) # goes out-of-bounds
		prints(p, i, 'after')
	pass
Spoiler: output
A 0 before
B 0 before

URL to the documentation page (if already existing):

I don't know of other places where this info might be, sorry if I just didn't look properly, but I didn't find any obvious places.

TL;DR

I really believe there should be a dedicated page for Error handling in GDScript (or Core?) that covers what exactly happens in case of errors in all cases, specially when not involving Error. If this can trick even experienced devs with unexpected behavior, imagine the novice ones!

Errors in Godot happen quite often, it's not a trivial subject, and I really think this subject deserves to have its own dedicated page, written by someone who understands the depths of Godot Core and GDScript.

@geekley
Copy link
Author

geekley commented Jan 22, 2025

Aaaaaand I thought I understood, but now I'm even MORE confused.

@tool
extends EditorScript

func _run() -> void:
	foo()
	pass

var array: Array[int] = [10, 11]
func foo() -> void:
	bar('A')
	bar('B')

func bar(p: String) -> void:
	for i: int in range(3):
		prints(p, i, 'before')
		prints(p, i, 'get', array[i]) # goes out-of-bounds when i == 2
		prints(p, i, 'after')
	pass
Spoiler: output
A 0 before
A 0 get 10
A 0 after
A 1 before
A 1 get 11
A 1 after
A 2 before

@tetrapod00 tetrapod00 added enhancement area:class reference Issues and PRs about the class reference, which should be addressed on the Godot engine repository topic:gdscript area:manual Issues and PRs related to the Manual/Tutorials section of the documentation content:new page Issues and PRs related to creation of new documentation pages for new or undocumented features labels Jan 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:class reference Issues and PRs about the class reference, which should be addressed on the Godot engine repository area:manual Issues and PRs related to the Manual/Tutorials section of the documentation content:new page Issues and PRs related to creation of new documentation pages for new or undocumented features enhancement topic:gdscript
Projects
None yet
Development

No branches or pull requests

2 participants