setget in Godot 4: Expected end of statement after variable declaration, found "Identifier" instead
By Eduardo Orellana · Updated
Godot 4 has no setget. Write the setter and getter on the variable itself: var health := 100: then an indented set(value): and get: block, or point at functions with var shield := 50: set = set_shield. The Godot 3 line var health = 100 setget set_health fails to parse with Expected end of statement after variable declaration, found "Identifier" instead.
What Godot is checking
The Godot 4 parser does not know setget. After var health = 100 it expects the end of the statement; it finds the word setget, an identifier, and reports that. The message does not mention setget, which is why it is hard to search for.
In Godot 4 the setter runs whenever the variable is assigned, from inside the class as well as from outside: Godot 3 skipped the setter for assignments inside the class unless you wrote self.health. Inside its own setter, assigning the variable stores the value directly, without calling the setter again.
Reproduce it
A Godot 3 property with setget in a Godot 4 project. The scene is one Node with this script.
extends Node
var health = 100 setget set_health
func set_health(value):
health = clamp(value, 0, 100)
func _ready():
self.health = 150
print(health)
What Godot 4.7.2 prints
Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org
SCRIPT ERROR: Parse Error: Expected end of statement after variable declaration, found "Identifier" instead.
at: GDScript::reload (res://answers/setget-in-godot-4/repro.gd:3)
ERROR: Failed to load script "res://answers/setget-in-godot-4/repro.gd" with error "Parse error".
at: load (modules/gdscript/gdscript_resource_format.cpp:46)Fix it
Both Godot 4 forms: health with an inline set and get, shield pointing at a named setter. The run assigns each from inside the class, and the setters run.
extends Node
var health := 100:
set(value):
health = clampi(value, 0, 100)
print("health set to ", health)
get:
return health
var shield := 50: set = set_shield
func set_shield(value: int) -> void:
shield = maxi(value, 0)
func _ready() -> void:
health = 150
health -= 30
shield = -5
print("health is ", health, ", shield is ", shield)
What the fixed script prints
Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org
health set to 100
health set to 70
health is 70, shield is 0Verified on Godot 4.7.2
Both scripts on this page were run headless on Godot 4.7.2 (4.7.2.stable.mono.official.ed1daf0bf) on 6 October 2026, and the output above is what Godot printed, unedited.
Where the check lives in Godot's source: [gdscript_parser.cpp line 695, the message](https://github.com/godotengine/godot/blob/4.7.2-stable/modules/gdscript/gdscript_parser.cpp#L695).
Questions
- Why does my setter now run when I assign the variable inside the class?
- Godot 4 calls the setter for every assignment, inside the class or outside, as the fixed run shows: health = 150 inside _ready printed health set to 100. Godot 3 called it from inside only for self.health.
Related
- The "export" keyword was removed in Godot 4
- The "onready" keyword was removed in Godot 4
- Every verified Godot 4 answer
- The "tool" keyword was removed in Godot 4: use @tool
- Invalid assignment of property or key with value of type on a base object of type 'Nil' in Godot 4
- Trying to assign a non-object value to a variable of type '…' in Godot 4
- Invalid call to function '…' in base '…'. Expected N argument(s) in Godot 4
- Invalid access to property or key on a base object of type 'Nil' in Godot 4
Flockbay's agent reads Godot's debugger output and fixes errors like this one in your project, on the official Godot.
Download Flockbay free