Repository: godotengine/godot (language: cpp)

Issue:
Godot 4.4 beta 1 'sample_baked: Offset is non-finite' error when using width curve in line2d
### Tested versions

- Reproducible in v4.4.beta1.official [d33da79d3]
- Not reproducible in v4.3.stable.official [77dcf97d8]

### System information

Godot v4.4.beta1 - macOS Sequoia (15.2.0) - Multi-window, 1 monitor - OpenGL 3 (Compatibility) - Apple M1 - Apple M1 (8 threads)

### Issue description

In 4.4 beta 1, when using a line2d with the following script attached...

```gdscript

extends Line2D

var queue : Array

func _physics_process(_delta: float) -> void:
	var pos = get_global_mouse_position()
	queue.push_front(pos)
	if queue.size() > 25:
		queue.pop_back()
	clear_points()
#
	for point in queue:
		add_point(point)

```

...and setting a weight curve, running the scene gives the following error

E 0:00:00:0377   sample_baked: Offset is non-finite
  <C++ Error>    Condition "!Math::is_finite(p_offset)" is true. Returning: 0
  <C++ Source>   scene/resources/curve.cpp:533 @ sample_baked()

There is no error in 4.3 stable

### Steps to reproduce

Add a line_2d, add the following script:

```gdscript

extends Line2D

var queue : Array

func _physics_process(_delta: float) -> void:
	var pos = get_global_mouse_position()
	queue.push_front(pos)
	if queue.size() > 25:
		queue.pop_back()
	clear_points()
#
	for point in queue:
		add_point(point)

```

Set a width curve in the line_2d

Run the scene

Or run the line_2d scene in the attached project

### Minimal reproduction project (MRP)

[test.zip](https://github.com/user-attachments/files/18494833/test.zip)


Discussion / hints:
Is a regression between 4.4 dev4 and dev 5, i'll bisect.
Bisected to #98625

![Image](https://github.com/user-attachments/assets/f782fa96-d261-40f0-8aad-bd9046c600fb)

<br>

From the pr that caused this regression the problem seems the mrp code adding the same point in the `Line2D` node, because the issue only happens when you don't move the mouse so the `queue` array will be filled with the same position and this will be passed to the `Line2D` node so for now i will not ping the pr author. A simple fix for that is only add points that wasn't added before like this:

```
extends Line2D

var queue : Array

func _physics_process(_delta: float) -> void:
	var pos = get_global_mouse_position()
	
	queue.push_front(pos)
	
	if queue.size() > 25:
		queue.pop_back()
	
	clear_points()
	
	for point in queue:
		if points.has(point) == false:
			add_point(point)

```

<br>

@AThousandShips I don't think this is a regression, just a bad code that was invalidated for avoid bigger problems, so i let in your hands if the pr author should be pinged about that.
That's a very valid point, but at minimum this needs to be documented *if* it is intentional, but the validity of this should also be discussed further, as it is not really obvious, even with documentation

So at minimum this should be documented, but we might want to build in some kind of function for this instead

Note that this change was done to prevent a crash in `Curve3D`, but unsure if the effects on `Line2D` were intentional

CC @KoBeWi any thoughts?
The error is probably coming from here:
https://github.com/godotengine/godot/blob/a7146ef807a7676f51a8a63cf4441ad647f4be66/scene/2d/line_builder.cpp#L192
LineBuilder may divide by 0.
Then it's likely a pre-existing bug that dates back to #28565... the recent changes just make the error explicit.

The LineBuilder logic indeed only computes `total_distance` conditionally, but it's then used throughout leading to multiple potential divisions by zero.

Fix patch:
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index d165d477f84b..f27d729e21d2 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -299,6 +299,9 @@ void Line2D::_draw() {
 	}
 
 	lb.build();
+	if (lb.indices.is_empty()) {
+		return;
+	}
 
 	RS::get_singleton()->canvas_item_add_triangle_array(
 			get_canvas_item(),
diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp
index ea949712ee2c..4a092675c98e 100644
--- a/scene/2d/line_builder.cpp
+++ b/scene/2d/line_builder.cpp
@@ -112,6 +112,11 @@ void LineBuilder::build() {
 		}
 	}
 
+	if (Math::is_zero_approx(total_distance)) {
+		// Zero-length line, nothing to build.
+		return;
+	}
+
 	if (_interpolate_color) {
 		color0 = gradient->get_color(0);
 	} else {


Test patch: