Invalid set index 'color' (on base: 'null instance') with value of type 'Color'

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

I am following this tutorial (Tool mode and maximizing - Title bar extras!). I don’t know how do solve the error. My node tree :
TitleBar (control node)

  • ColorRect
  • HBoxContainer
    – MinimizeButton
    – CloseButton

The error output

The error is Node not Found : ColorRect
res://TitleBar.gd:11 - Invalid set index ‘color’ (on base: ‘null instance’) with value of type ‘Color’

tool
extends Control

export(Color) var background_color = Color(0, 0, 0, 1) setget set_background_color

var following = false
var dragging_start_position = Vector2()

func set_background_color(value):
    background_color = value
    $ColorRect.color = background_color

I think i already add the ColorRect in TitleBar, but it still show “Node not found : ColorRect”. I try to use get_node(“ColorRect”) and it doesn’t work too. I can change the TitleBar background_color Immediately, but i can’t play the scene. How do i fix this error?

:bust_in_silhouette: Reply From: Zylann

I think you are running into a particular behavior to be aware of:
When Godot loads your scene, it creates nodes one by one and assigns their properties. Then later on, it is added to the tree.
When it creates TitleBar, it assigns background_color, but your code tries to access ColorRect. However, it is possible that node wasn’t created yet. It might not even be in the tree either.

When you have setters like this, you are only guaranteed to access properties of your own object. Any external object such as child nodes or the scene tree will be available only later (i.e your node may not necessarily be in the tree immediately). If they happen to work, it might be chance: objects creation order can vary unexpectedly, so code relying on that can break easily.

So to make this code more robust, you have to first check if the node is present, and if not, defer the assignment in _ready because that’s when you know the node will be there.

func _ready():
    $ColorRect.color = background_color

func set_background_color(value):
    background_color = value
    if has_node("ColorRect"):
	    $ColorRect.color = background_color

UPDATE:
Here is the explanation why it worked in the video:
If you set a property to be the same value as its default value, Godot does not save it in the scene. Then it doesn’t sets it when the scene loads.

When the guy tests the property in the editor, nodes are in the tree already so it’s all fine and dandy. And then when he runs the game, it works because he had reset the value to default before, so it was not saved into the scene, so never set on load and no error for him. But I bet he will find that soon :stuck_out_tongue:

Thank you for your reply. I think i miss the sequence of creating node in godot. Gratefully, you solve my another question about the video.

Yang | 2019-08-19 11:21