Strange resizing of panelcontainers

I want to make a popup window that shows messages ingame.

So i made a scene with the following structure:
-PanelContainer
–NinePatchRect
–MarginContainer
—VBoxContainer
NinePatchRect and MarginContainer share same margins.
The following simple script should handle all, right?:

extends PanelContainer

class_name messages_banner

@export var default_color: Color = Color(1,0,0)
@export var font_size: int = 28

var labels: Array[Label]
var messages: Array[String]

func set_message(texts: Array, colors: Array):
hide()
for l in labels:
l.queue_free()
labels.clear()
var num_rows: int = texts.size()

for r in range(0, num_rows):
	var l = Label.new()
	labels.append(l)
	l.mouse_filter = Control.MOUSE_FILTER_PASS

	l.text = str(texts[r])
	if r < colors.size():
		l.modulate = Color(colors[r] as Color)
	else:
		l.modulate = default_color
	l.add_theme_font_size_override("font_size",font_size)
	l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
	l.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
	$MarginContainer/VBoxContainer.add_child(l)
show()

Turns out, the panel keeps resizing its y size as the game proceeds.
First message is fine.
Then, as messages change, the y size increases, first abruptly, then slowly, maybe 1 pixel per time.
It also never goes back. If at a certain message is made of 4 lines, the size increases a lot wrt the preceeding 2 lines message; if the following message is again of 2 lines, the size remains for 4 lines.

This is so odd. Wtf is going on?!

I did notice that too, and my solution for this is to set the size of the PanelContainer to Vector2.ZERO before you add any children to it. Then it will scale from zero upwards properly.

I’m not sure if that’s a bug or a desired behavior.

Nice try, but it did not work for me. I also tried to set the size of everything else to zero… does not work

Tried a lot of thing, nothing did work.

Then I did this
Instead of having a fixed scene in my tree and calling the set_message on it…

…I instantiate a new scene every time. Every. Fucking. Time.
And queue free the previous of course.

Seems to work, but God(ot?) knows what’s wrong with this resizing.

related: godot control nodes suck.