Skip to content

Regression in #9920: post-process re-parse clobbers GCodeProcessorResult state, breaks H2C/H2D nozzle auto-mapping #10528

@adele-with-a-b

Description

@adele-with-a-b

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

  1. H2C printer (H2D has identical send-flow; inferred-affected).
  2. Use any stock H2C process preset (e.g. 0.20mm Standard @BBL H2C).
  3. In Process → Others → Post-processing scripts, add any command, e.g. cat.
  4. Slice a single-filament plate.
  5. Click Print / Send.
  6. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions