Invalid assignment of property or key with value of type of 'Color' on a base object of type 'Nil'

Godot Version

4.3

Question

Hello I am trying to create an info card that shows the stats of a given unit in my game.
But when I try to create var bg_color: Color and then call that variable later inside a ‘Set’ @export var unit_stats: UnitStats : set = _set_unit_stats using bg_style.bg_color = bg_color it comes up with
“Invalid assignment of property or key ‘bg_color’ with value of type of ‘Color’ on a base object of type ‘Nil’”

Can you share your code? Or just the part of it that works with this variable, you have to initialize it somewhere, just setting its type doesn’t create it.

Sorry for the delay.
I first set bg_color at the start of the gd script which only next comes up in the ‘set’ I created.

@export unit_stats: UnitStats : set = _set_unit_stats
@onready var border: Panel = %Border
@onready var bg_style: StyleBoxFlat = border.get_theme_stylebox("Panel")
var bg_color: Color

func _set_unit_stats(value: UnitStats) -> void:
    bg_color = UnitStats.RARITY_COLORS[unit_stats.rarity]
    bg_style.bg_color = bg_color

@export unit_stats: UnitStats : set = _set_unit_stats
Well this isn’t the code you are actually using since you should be getting an error on the first line where you missed ‘var’.
@export var unit_stats: UnitStats : set = _set_unit_stats

Since that isn’t causing the title error we have to assume what you are going for.
I would test border from here to see if it found the node.
@onready var border: Panel = %Border
Remember in order to access a scene unique node via %node it must be present in the scene.

As an aside; you don’t set unit_stats in the set function. It will remain what you set it as in the editor.

Personally, I am not a fan of the callable set/get design choice. To me your code would be much more readable this way:

@export var unit_stats: UnitStats : 
    set(value):
        bg_color = UnitStats.RARITY_COLORS[unit_stats.rarity]
        bg_style.bg_color = bg_color    
        #unit_stats = value

I think you should apply these first, they are useful recommendations: Invalid assignment of property or key with value of type of 'Color' on a base object of type 'Nil' - #4 by sancho2
But then, we need to know what the value of bg_style is, if you can see it in the debugger then tell us from there otherwise put a print(bg_style) after setting it and let us know the output. I guess it returns null

Thx @sancho2, the code looks better but %Border gives me ‘Object#null’ on 'print(%Border) and

@Mahan print(bg_style) does give ‘null’ except for when I remove my UnitStats.tres (which is the stats to one of my units) from the export and leave it empty giving me my Stylebox and Border ID’s

Can you share your scene tree? The script cannot find %Border

Border is the 4th down

Its as I suspected that border being null means that the next onready which is derived from border is also going to be null.
So then why is border not found?
Can you drag the node into the code window, press ctrl, and drop it in?
Or is this a resource and the border node not actually stored with the tres?
Secondly (but almost certainly not relevant), is there a reason for using a scene unique node here?

2 Likes

I dragged the border node into the code and held control giving me the @onready variable for border.
border is not a resource, it is a panel with a new flat stylebox.
The reason I am using a scene unique node is because I intend to call it later, for highlighting purposes later down the road.

Also removing the Scene unique name ends up with the same error

What happens if you add this?

func _ready() -> void:
    print(get_path())
    print_tree()

That will give me

/root/UnitCard
.
BackDrop
BackDrop/Traits
Bottom
Bottom/MarginContainer
Bottom/MarginContainer/NameContainer
Bottom/MarginContainer/NameContainer/UnitName
Bottom/MarginContainer/NameContainer/GoldContainer
Bottom/MarginContainer/NameContainer/GoldContainer/GoldIcon
Bottom/MarginContainer/NameContainer/GoldContainer/GoldCost
Border
UnitIcon
EmptyPlaceHolder

which Border is in, but still comes up as ‘Nil’

I was thinking that UnitCard was a resource. A resource won’t carry child nodes by default.
But gertkeno’s test prints show that border is a scene node so that line of thinking is out (sort of).
What is interesting here is that despite the path showing UnitCard that node doesn’t come up when you print the tree.
Why is that?
Run the game and select “Remote” from the scene tree and see if UnitCard is in the scene.
Is it the case where UnitCard is an instantiated scene and not added as a child of a tree node?

If I remove the code that doesn’t cause the error then I get everything as normal, but nothing will show up in remote with the error other than root

Also UnitCard is the Top-most node in the scene, I didn’t put any 2d or control node above it.

Whoops my bad.
print_tree() doesn’t seem to print the root node. (This perplexes me). In fact it prints it as a “.”
Try print_tree_pretty()

So now I too am confused since Border is clearly there.
Try printing out border in that ready function:

func _ready() -> void:
    print(get_path())
    print_tree()
    print(%Border)

Or try reverting Border from a scene unique node back to ordinary $ node.

And it probably isn’t impacting but the picture of your scene tree shows “UnitCar” but the path you print out shows “UnitCard”. This makes me wonder if you are showing us what code and design you are actually using or editing it before posting.

I have found the root of the problem which is this line which changes border stylebox.border color border_sb.border_color = border_color

It seems that any code trying to manipulate the stylebox in any way shape of form is a no go and because this is in my @export ‘set’. any code func _ready() code activates it will show up with the error aslong as border stylebox is being manipulated.

Also sorry if things don’t match up from different replies as yes I have been editing my code before posting, trying to find other solutions out on the web, but for some reason it seems that my error has just never shown up before, so idk. I might just have to create separate unit cards if I can’t find a solution.

I have just decided remove my ‘set’ entirely and upon being called in a new func and upon _ready() just set the stats, colors and everything under that. That will work for most of the features I want but leaves out some that I won’t bother on