Summary
PR #9920 (merged as 3722c98a3, first shipped in 2.6.0 Public Release) introduced a regression on H2C/H2D printers: any sliced plate with a post_process script entry causes the error
The printer failed to build the nozzle auto-mapping table { code: 1 }. Please refreash nozzle information.
(Typo "refreash" is the original; reliable grep anchor for the exact error string.)
The error fires regardless of script content — even a no-op like cat or ls reproduces it. The trigger is the re-parse code path itself, not anything the script outputs.
Affected versions
Reproduction
- H2C printer (H2D has identical send-flow; inferred-affected).
- Use any stock H2C process preset (e.g.
0.20mm Standard @BBL H2C).
- In Process → Others → Post-processing scripts, add any command, e.g.
cat.
- Slice a single-filament plate.
- Click Print / Send.
- Dialog shows
The printer failed to build the nozzle auto-mapping table { code: 1 }.
Removing the post-process entry fixes the error. Rolling back to 2.5.3 fixes it.
Root cause
In src/slic3r/GUI/BackgroundSlicingProcess.cpp finalize_gcode():
if (post_process && !post_process->values.empty() && m_gcode_result) {
m_print->set_status(97, _utf8(L("Updating preview with post-processed G-code")));
GCodeProcessor processor;
processor.process_file(m_temp_output_path);
*m_gcode_result = std::move(processor.extract_result()); // ← regression
}
GCodeProcessorResult carries a lot of slicer-computed, config-derived state beyond move vertices — in particular:
filament_maps (filament → extruder)
nozzle_group_result (MultiNozzleUtils::MultiNozzleGroupResult)
filament_change_sequence
required_nozzle_HRC
nozzle_type
extruder_colors
print_statistics
None of these can be reconstructed from G-code text alone; they come from the full config during slicing.
The fresh GCodeProcessor::process_file only parses G-code text, so those fields come out empty or default. std::move into *m_gcode_result replaces the slicer-populated state with the empty defaults.
On H2C/H2D, SelectMachineDialog::CheckStatusAndShow() reads get_nozzle_count(LOGIC_R_EXTRUDER_ID) from the now-empty nozzle group result, then calls ctrl_get_auto_nozzle_mapping() with malformed filament info. Printer's mapping solver returns result="fail", errno=1, which the UI surfaces as the error above.
Single-extruder printers don't hit this visibly because CheckStatusAndShow short-circuits before the mapping query when no right-extruder nozzles are used. State is still being clobbered on those printers — it just doesn't break any currently-exercised code path.
Proposed fix
Only update fields that reflect G-code text content (moves, lines_ends). Preserve all config-derived state.
if (post_process && !post_process->values.empty() && m_gcode_result) {
m_print->set_status(97, _utf8(L("Updating preview with post-processed G-code")));
GCodeProcessor processor;
processor.process_file(m_temp_output_path);
GCodeProcessorResult&& reparsed = processor.extract_result();
m_gcode_result->moves = std::move(reparsed.moves);
m_gcode_result->lines_ends = std::move(reparsed.lines_ends);
}
(Rvalue-reference binding instead of value is required — GCodeProcessorResult's copy constructor is implicitly deleted due to a mutable std::mutex member.)
This preserves the original #9920 goal (preview reflects the post-processed toolpath) while preserving the slicer-computed state the send flow depends on.
Tradeoff worth flagging
This fix assumes moves and lines_ends are sufficient to make the preview reflect any change a post-process script could make. That's true for scripts that reorder or rewrite extrusion moves within the existing tool-change structure — e.g. BrickLayers. I have not audited the general case.
If a post-process script adds or removes tool changes, fields like filament_change_sequence, print_statistics, and extruder_colors will stay tied to the pre-post-process sequence rather than the executed G-code. Consequences: time estimates, flush-weight calculations (GetFlushWeight() reads filament_change_sequence), and per-extruder visualization in the preview would be stale for the post-processed output.
This is still the right tradeoff relative to the current bug (which makes the send flow completely non-functional on H2C/H2D with any post_process entry), but it's a narrower correctness property than the original #9920 was aiming for. If there's a known use case where post-process scripts alter tool-change structure and the existing time/flush outputs need to reflect that, the fix would need to selectively update more fields rather than the all-or-nothing approach #9920 originally took.
Context
PR #9920 was contributed by me to support community post-processing tools like BrickLayers. The re-parse behavior was desirable because without it the preview showed pre-post-process toolpaths after BrickLayers had already rewritten the G-code. The regression was missed in review because:
(a) I tested on a single-extruder printer at the time; the bug only surfaces on multi-nozzle (H2C/H2D).
(b) The bug only triggers during the send-to-printer flow, which isn't exercised in slice/preview testing.
Validated end-to-end on a local patched build against an H2C with multiple filament colors, BrickLayers post-process enabled. Fix PR: #10529.
Summary
PR #9920 (merged as
3722c98a3, first shipped in 2.6.0 Public Release) introduced a regression on H2C/H2D printers: any sliced plate with apost_processscript entry causes the error(Typo "refreash" is the original; reliable grep anchor for the exact error string.)
The error fires regardless of script content — even a no-op like
catorlsreproduces it. The trigger is the re-parse code path itself, not anything the script outputs.Affected versions
Reproduction
0.20mm Standard @BBL H2C).cat.The printer failed to build the nozzle auto-mapping table { code: 1 }.Removing the post-process entry fixes the error. Rolling back to 2.5.3 fixes it.
Root cause
In
src/slic3r/GUI/BackgroundSlicingProcess.cppfinalize_gcode():GCodeProcessorResultcarries a lot of slicer-computed, config-derived state beyond move vertices — in particular:filament_maps(filament → extruder)nozzle_group_result(MultiNozzleUtils::MultiNozzleGroupResult)filament_change_sequencerequired_nozzle_HRCnozzle_typeextruder_colorsprint_statisticsNone of these can be reconstructed from G-code text alone; they come from the full config during slicing.
The fresh
GCodeProcessor::process_fileonly parses G-code text, so those fields come out empty or default.std::moveinto*m_gcode_resultreplaces the slicer-populated state with the empty defaults.On H2C/H2D,
SelectMachineDialog::CheckStatusAndShow()readsget_nozzle_count(LOGIC_R_EXTRUDER_ID)from the now-empty nozzle group result, then callsctrl_get_auto_nozzle_mapping()with malformed filament info. Printer's mapping solver returnsresult="fail",errno=1, which the UI surfaces as the error above.Single-extruder printers don't hit this visibly because
CheckStatusAndShowshort-circuits before the mapping query when no right-extruder nozzles are used. State is still being clobbered on those printers — it just doesn't break any currently-exercised code path.Proposed fix
Only update fields that reflect G-code text content (
moves,lines_ends). Preserve all config-derived state.(Rvalue-reference binding instead of value is required —
GCodeProcessorResult's copy constructor is implicitly deleted due to amutable std::mutexmember.)This preserves the original #9920 goal (preview reflects the post-processed toolpath) while preserving the slicer-computed state the send flow depends on.
Tradeoff worth flagging
This fix assumes
movesandlines_endsare sufficient to make the preview reflect any change a post-process script could make. That's true for scripts that reorder or rewrite extrusion moves within the existing tool-change structure — e.g. BrickLayers. I have not audited the general case.If a post-process script adds or removes tool changes, fields like
filament_change_sequence,print_statistics, andextruder_colorswill stay tied to the pre-post-process sequence rather than the executed G-code. Consequences: time estimates, flush-weight calculations (GetFlushWeight()readsfilament_change_sequence), and per-extruder visualization in the preview would be stale for the post-processed output.This is still the right tradeoff relative to the current bug (which makes the send flow completely non-functional on H2C/H2D with any post_process entry), but it's a narrower correctness property than the original #9920 was aiming for. If there's a known use case where post-process scripts alter tool-change structure and the existing time/flush outputs need to reflect that, the fix would need to selectively update more fields rather than the all-or-nothing approach #9920 originally took.
Context
PR #9920 was contributed by me to support community post-processing tools like BrickLayers. The re-parse behavior was desirable because without it the preview showed pre-post-process toolpaths after BrickLayers had already rewritten the G-code. The regression was missed in review because:
(a) I tested on a single-extruder printer at the time; the bug only surfaces on multi-nozzle (H2C/H2D).
(b) The bug only triggers during the send-to-printer flow, which isn't exercised in slice/preview testing.
Validated end-to-end on a local patched build against an H2C with multiple filament colors, BrickLayers post-process enabled. Fix PR: #10529.