Quick answer: A NodePath is a relative string — it doesn’t follow nodes when you reparent them. Use scene-unique names (%Name) which are location-independent, or re-assign the path.

A C# component has [Export] private NodePath HealthBarPath. After moving the health bar into a new container, GetNode returns null — the stored path no longer resolves.

NodePaths Are Just Strings

A NodePath like ../UI/HealthBar is resolved relative to the owner at runtime. Reparent the target and the string is now wrong — nothing updates it for you.

Use Scene-Unique Names

In the editor, right-click a node → “% Access as Unique Name”. Then:

private ProgressBar _healthBar;

public override void _Ready()
{
    _healthBar = GetNode<ProgressBar>("%HealthBar");
}

%HealthBar finds the node anywhere in the scene by its unique name — reparenting doesn’t break it.

Or Export the Node Directly

[Export] private ProgressBar HealthBar { get; set; }

Godot 4 supports exporting node references directly, not just paths. The reference survives reparenting within the same scene because it’s resolved on save, not by string at runtime.

Verifying

Reparent the health bar into a different container. The component still finds it. Restructure the scene freely — unique names and direct exports keep resolving.

“NodePaths are brittle strings. Prefer % unique names or direct node exports.”

Reserve raw NodePath exports for cases where the path genuinely is the data (e.g. configurable targets) — for ‘my health bar’, use a unique name.