Repository navigation
URGENT: QIDI Box - never start a print on the printer's stale slot mapping - #643
Merged
Merged
Conversation
The QIDI Box firmware feeds T<n> from the slot its saved variable value_t<n> names, and only the sending slicer sets it. #611 sent the mapping only from the desktop send dialog, and only when a device was picked and its 3 s probe answered. Every other start went out with no mapping, so the printer reused its last print's slots: a PLA plate fed the ASA in the Box, at PLA settings. Holes closed: - hub / phone / Stream tab send and archive reprint (RemoteSend prepare_host / prepare_from_record -> run_host) uploaded with print=true and no Box script at all, with no dialog anywhere. run_host now reads the printer, maps every used filament material-first and sends the Box script before the upload, or refuses with the reason. - desktop dialog with no device row (device list empty: build_device_ui returned early, nothing probed): a Box-capable QIDI preset now gets its own address as the device, like Elegoo Link. - desktop dialog after a failed probe / with filaments left "As sliced": "Upload and Print" now asks qidi_send_policy. Unreadable Box: Upload only (default), Retry, or an explicit Print anyway. Unmapped filament: refused with the list. Slot of another material: warn and confirm. - "Print all" counted only the current plate's filaments. The decision is one pure function, PrintHostDevices::qidi_send_policy, with qidi_auto_mapping / qidi_box_capable_model / filament_types_match, covered by tests/slic3rutils/qidi_send_policy_tests.cpp. Deft
…s unreadable
Owner repro: Qidi X-Max 4 preset, physical printer at an address with
no printer behind it, probe answered HTTP 404 -> plain dialog, no QIDI
options, Upload and Print enabled. The profile's printer_model now
decides too: a Box-capable model whose printer failed the probe, or
answered without multi_color_controller, is UploadOnlyNoProbe. The
dialog says so in words ("Couldn't read the QIDI Box: the printer would
use its last saved slot mapping"), Upload stays the default, and Upload
and Print asks (Upload only / Retry / Print anyway). The QIDI options
are not offered blind: they need the printer to answer.
Deft
…longer probe From the owner's 2.4.6.2 logs and screenshot (PLA calibration fed from the ASA slot): - The dialog probe timed out at 3 s on a real QIDI on the LAN, so no Box rows and no options. A Box-capable model now waits 10 s. - QIDIStudio 2.07 does not read multi_color_controller at all: it reads save_variables (box_count, filament_slot<n>, color_slot<n>) and the printer's config/officiall_filas_list.cfg. When multi_color_controller names no materials the probe now reads those, and save_variables' enable_box / box_count also mark QIDI firmware with a Box. - The likely mechanism of the wrong slot: with the Box on and no rows (nothing readable) or a filament left "As sliced", qidi_start_script sent "enable_box VALUE=1" alone and the printer kept value_t0 from the last (ASA) print. qidi_send_policy now refuses that, an empty or unreadable Box defaults to on (never silently to the toolhead spool), and after the script both the desktop queue and the hub send read save_variables back and refuse to upload unless enable_box and every value_t<n> match. - The "sent" lines are logged at warning level, so the mapping is in the user's log next time. - Material mismatch (PLA filament -> ASA slot) asks before printing for every host whose slots name materials (CANVAS dialog included). Deft
…ons unread Owner hand test (X-Max 4 preset, HTTP 404): - The notes under the printer row wrapped at CONTENT_WIDTH * em_unit, some 2400 px, so the new QIDI note stretched the dialog to the screen. They now wrap at FromDIP(460), and the note is shorter. - A Box-capable QIDI that did not answer still shows Use QIDI Box (on), Auto bed leveling, Timelapse and, where QIDIStudio's profiles have it, Polar cooler. They are remembered as before and go out at send time only if the printer answers then; the queue reads its state first and stops the send with a message when it does not. Deft
aceRage
marked this pull request as ready for review
October 20, 2026 22:19
aceRage
added a commit
that referenced
this pull request
Oct 20, 2026
aceRage
added a commit
that referenced
this pull request
Oct 20, 2026
update_mapping_note() keeps the no-rows guard and adds #643's QIDI Box problem lines. On a QIDI Box those lines replace the swatch map's own type/colour mismatch lines, so a wrong-material slot is reported once. Deft
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
URGENT safety fix. On 2.4.6.2, a QIDI printer with a QIDI Box was started on a plate sliced as PLA (PLA and ASA in the Box) with no Box mapping sent, and printed the ASA at PLA settings.
Root cause
The QIDI Box firmware feeds
T<n>from the slot named by its saved variablevalue_t<n>. Only the sending slicer sets that variable. #611 sentSAVE_VARIABLE enable_box/value_t<n>from exactly one place:PrintHostSendDialog::qidi_start_script()(PrintHostDialogs.cpp), which is empty unlessm_device_status.qidiis true. The printer then reuses whatever its previous print left invalue_t<n>. These paths start a print with no mapping:RemoteSend::prepare_host(RemoteSend.cpp ~644-720) andprepare_from_record(printhost branch, ~1287-1351) setpost_action = StartPrint, andrun_host(~1582) callshost->upload()directly. That upload is Octo/Moonrakerprint=true. There is no probe and no Box script, and nothing on the desktop pops up. This matches "the pre-send dialog never popped up".refresh_device_status()getsqidi = false. The dialog is then the plain one, with no Box rows and no QIDI options, and "Upload and Print" is enabled. The owner reproduced this on an X-Max 4 preset.build_device_ui()returns early whenm_devices.empty()(PrintHostDialogs.cpp ~553). That happens with a presetprint_hostand the device deleted from the list (migrate never re-imports it). Nothing is probed.value_t<n>is sent for it, so it still loads from the stale slot.plate_filaments_for_sendonly marked the current plate's filaments as used.The sidebar Print / Send buttons, print plate and print all all go through
send_gcode_legacy, so they always show the dialog. There is no "don't show again" or remembered post-action for print hosts. QIDI profiles have nohost_type, so they default tooctoprint(the OctoPrint class talking to Moonraker), which is probed.What the owner's logs and screenshot show (PLA calibration fed from the ASA slot)
2026-10-19-18-38-46.log.0:m_device_status.qidiwas true, and the print started. Only the bed-leveling call failed ("Klippy Write Request Error"). The "sent ... (Box mapping X)" line was info level, so the mapping that went out is not in the log. It is now logged at warning level.Plater::calib_pa/calib_flowrate/calib_temp, Plater.cpp ~20160 / 20664 / 20720) only builds a normal project withnew_project+add_model. Its object prints on filament 1 (T0,value_t0) and is sent with the same sidebar Print ->send_gcode_legacy-> dialog.multi_color_controller(the string is not in its binary). It reads the Box fromsave_variables(box_count,filament_slot<n>,color_slot<n>) plus the printer'sconfig/officiall_filas_list.cfg. The value quotingVALUE="'slot%s'"and the 0-based box*4+slot numbering match ours.slots_have_filamentsfalse), so no rows are shown. A filament can also be left "As sliced" because its type did not match. In both casesqidi_start_scriptsendsSAVE_VARIABLE enable_box VALUE=1alone, Moonraker answers OK, and the printer keepsvalue_t0 = slot<ASA>from the earlier ASA print.Fix
PrintHostDevices::qidi_send_policy(QidiSendFacts)is one pure function that every path uses. Its results are NotApplicable / Start / UploadOnlyBusy / UploadOnlyNoProbe / NeedsMapping / ConfirmTypeMismatch. The helpers areqidi_box_capable_model(profile: Q2/Q2C, X-Max 4, X-Plus 4, X-Plus 5),filament_types_matchandqidi_auto_mapping(material-first, as the dialog's auto-match).multi_color_controller): Upload only (the default and the auto-answer), Retry, or an explicit "Print anyway".mapping_choice_positions(), so it also works with the Bambu-style swatch map for third-party send dialogs (CANVAS, U1, QIDI Box) #625/Happy Hare and AFC slot reading for the Moonraker send dialog #612 swatch panel.arm_qidi_guard+qidi_guard_start):enable_box+value_t<n>) before the upload. Otherwise it refuses with the reason and nothing is sent.multi_color_controllernames no materials, the probe reads the Box the QIDIStudio way (save_variables+officiall_filas_list.cfg).enable_box/box_countinsave_variablesalso mark QIDI firmware with a Box.enable_box 0) feeds whatever is in the toolhead, so it is only ever an explicit untick.save_variablesback. Ifenable_boxand everyvalue_t<n>do not match what was sent, they refuse to upload.Other hosts: unchanged. The exceptions are one extra read-only probe on a remote print to an
octoprint-type host, and "print all" marking the filaments of every plate.Same hole elsewhere (reported, not fixed)
Elegoo CANVAS remote send:
prepare_hostsends noextended_info, so noslot_map. The printer gets the start without a mapping, exactly as before the CANVAS work. This is a different firmware: there is no saved stale variable, but the result is still unmapped. It needs a CANVAS read inrun_host.U1: no hole. The remote path is the LAN
snapmakerkind, withauto_matchplusstart_print_mapped, and the desktop uses the connect page.Device tab file list "Print" (
RemoteFileGridModel::StartPrint->MoonrakerFiles::start_print) on a QIDI: it starts a stored file on the stale mapping, the same as the printer's own touchscreen. Follow-up.Flashforge IFS dialog: it has its own slot dialog and does not use these rows, so it is not covered by the mismatch confirmation.
Unverified on hardware (nobody here has a QIDI Box)
officiall_filas_list.cfglayout ([fila<id>] type =,[colordict] <id> = #RRGGBB) is inferred from the property-tree keys in the QIDIStudio binary.filament_slot<n> > 0is loaded.Compatibility with #625 / #612
The guard reads
mapping_choice_positions()andm_mapping_filament, which the swatch panel answers. Expect textual conflicts inPrintHostDialogs.cpp:update_mapping_note(#625 F14 removed its early return),rebuild_mapping_rows, and the QIDI note inrefresh_device_status. #616's async probe would needconfirm_qidi_startto run only after the probe finishes. #620 touchesinit()(the Upload and Print handler).Tests
tests/slic3rutils/qidi_send_policy_tests.cppcovers the policy matrix, including "profile says QIDI Box, probe failed" and the owner's 404 repro. It also covers the reported PLA/ASA plate, PETG not in the Box, busy, Box off or absent, and the U1 not being affected.Hand test (owner, no QIDI): with a QIDI X-Max 4 preset and a dead address, check that the note shows, that Upload is the default, and that Upload and Print shows Upload only / Retry / Print anyway.