Skip to content

[Bug] Exported presets with "nil" variant slots cause value set to MAX (eg: nozzle to 1500C when High Flow nozzle is selected) #10583

@Jingxi-Polymaker

Description

@Jingxi-Polymaker

Bambu Studio Version

2.6.1.55

Where is the application from?

Bambu Lab GitHub releases

OS version

macOS 26.4.1 (25E253)

Additional system information

This bug can replicate on all system

Printer

All printer

How to reproduce

  1. Create a new filament preset (e.g., based on Generic PETG).
  2. Change only the Standard nozzle temperature (e.g., set to 270°C).
  3. Leave the High Flow nozzle temperature untouched / at default.
  4. Export the filament preset via File → Export → Export Presets.
  5. Import the exported preset via File → Import → Import Presets.
  6. In the printer settings, select the High Flow nozzle.
  7. Slice any model and check the temperature settings or generated G-code.

Actual results

The imported preset JSON contains:

"nozzle_temperature": [
    "270",
    "nil"
],
"nozzle_temperature_initial_layer": [
    "270",
    "nil"
]

When the High Flow nozzle is selected, BambuStudio deserializes "nil" into INT_MAX (2147483647). This propagates into the slicer UI and G-code:

M104 S2147483647

The UI displays this as approximately 1500°C (or the firmware's max cap), which is physically impossible and potentially harmful.

Expected results

After import, the High Flow nozzle temperature should fall back to the inherited/default value (e.g., 250°C or whatever the parent preset defines). It should not become an extreme invalid value.

Project file & Debug log uploads

additional information:
Root Cause (from code inspection)

Export writes "nil": Preset::save() uses set_with_nil() to serialize unset variant slots as the literal string "nil" to preserve diff/inheritance state.
Import maps "nil" to sentinel: ConfigOptionIntsNullable::deserialize() converts "nil" → std::numeric_limits::max() (2147483647).
No fallback: get_at() returns the sentinel directly for valid indices without checking is_nil(). Most G-code temperature consumers only check temp > 0, which INT_MAX passes.
Critical mismatch — Import vs. Restart paths:
Right after import (PresetBundle::import_json_presets()):
Uses new_config.apply(std::move(config)) which blindly copies the child preset's nil sentinel into memory via set(). The High Flow slot becomes INT_MAX/NaN in the active config.
After restart (PresetCollection::load_presets()):
Rebuilds the preset from parent config first, then
calls update_diff_values_to_child_config() → set_only_diff(). This only copies child slots where !is_nil(...), so nil slots are skipped and the parent's concrete value remains in memory. This masks the bug in the UI, but the JSON file on disk still contains "nil" — so any fresh import re-triggers the corruption.
This path mismatch is why the bug appears immediately after import but seems "fixed" after restarting BambuStudio.

Archive.zip

Checklist of files to include

  • Log file
  • Project file

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions