From 075b03975f066199e4104ae0bc681577fceef6dd Mon Sep 17 00:00:00 2001 From: HMITCHR <265609730+HMITCHR@users.noreply.github.com> Date: Mon, 12 Oct 2026 18:55:02 -0600 Subject: [PATCH] Read the initial filament start G-code through get_at() (#16080) A filament_start_gcode list shorter than the filament count made the Bambu start-of-export path throw std::out_of_range. Use get_at() like the other filament_start_gcode reads, and add a regression test. --- src/libslic3r/GCode.cpp | 2 +- tests/fff_print/test_gcodewriter.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index b79a386324..f423681c9d 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -4262,7 +4262,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato config.set_key_value("nozzle_diameter_at_nozzle_id", new ConfigOptionFloats(get_nozzle_diameters_by_nozzle_id(group_result.get()))); config.set_key_value("nozzle_volume_types", new ConfigOptionStrings(get_nozzle_volume_types_by_nozzle_id(group_result.get()))); config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); - std::string filament_start_gcode = this->placeholder_parser_process("filament_start_gcode", print.config().filament_start_gcode.values.at(initial_non_support_extruder_id), initial_non_support_extruder_id,&config); + std::string filament_start_gcode = this->placeholder_parser_process("filament_start_gcode", print.config().filament_start_gcode.get_at(initial_non_support_extruder_id), initial_non_support_extruder_id,&config); file.writeln(filament_start_gcode); // Mark the first filament used in print. Multi-nozzle printers (H2C) get ";VT%d H%d" where // H = dynamic ? nozzle_id : -1; existing single-nozzle printers keep the bare ";VT%d" so their diff --git a/tests/fff_print/test_gcodewriter.cpp b/tests/fff_print/test_gcodewriter.cpp index 170dfabae3..d491527db6 100644 --- a/tests/fff_print/test_gcodewriter.cpp +++ b/tests/fff_print/test_gcodewriter.cpp @@ -1748,3 +1748,29 @@ TEST_CASE("Percent accelerations resolve against the option they are a percentag REQUIRE(accelerations_by_role[role_name] == std::set{ value }); } } + +TEST_CASE("Initial filament start G-code tolerates a list shorter than the filament count", "[GCodeWriter]") +{ + // Two filaments but only one filament_start_gcode entry, and the only object prints on + // filament 2, so the BBL export starts on a filament past the end of the list. + DynamicPrintConfig config = multifilament_config(2); + config.set_key_value("filament_start_gcode", new ConfigOptionStrings({"; filament start"})); + + Model model; + auto *obj = model.add_object(); + obj->add_volume(cube(20)); + obj->add_instance(); + obj->config.set_key_value("extruder", new ConfigOptionInt(2)); + + Print print; + print.is_BBL_printer() = true; + arrange_objects_on_test_bed(model, config); + for (auto *mo : model.objects) { + mo->ensure_on_bed(); + print.auto_assign_extruders(mo); + } + print.apply(model, config); + print.validate(); + + REQUIRE_NOTHROW(Slic3r::Test::gcode(print)); +}