Bug report: bpm.print_3mf_file fails with 07FF_8012 "Failed to get AMS mapping table" when printing from the external spool (no AMS)
- Library:
bambu-printer-manager (bpm), >=1.0.2
- Affected call:
BambuPrinter.print_3mf_file(...)
- Symptom: Print never starts; printer reports HMS error
07FF_8012 — "Failed to get AMS mapping table".
- Affected hardware: Single-nozzle printers run without an AMS (external spool), printing a single plate. Confirmed against our P2S / H2S / X1.
- Workaround status: We had to stop using
print_3mf_file and build/publish the project_file MQTT command ourselves. Details below.
What we expected
Calling print_3mf_file to print one plate of an uploaded .3mf from the external spool (no AMS attached) should start the print.
We tried what the API suggests for "no AMS":
self._printer.print_3mf_file(
name=remote, # absolute SD path, e.g. "/magprint_job.gcode.3mf"
plate=1,
bed=PlateType.AUTO,
use_ams=False,
ams_mapping="", # empty -> bpm omits the field entirely
bedlevel=bed_level,
flow=flow_calibration,
timelapse=timelapse,
)
What actually happens
The print does not start. The printer raises HMS 07FF_8012 "Failed to get AMS mapping table".
Root cause is how the firmware interprets the AMS mapping fields in the project_file command, and bpm does not encode them correctly for external-spool / single-nozzle printing:
-
ams_mapping (flat array). The firmware rejects raw tray IDs (254 / 255) in the flat ams_mapping. For external-spool printing it must be [-1]. Passing a non-empty mapping makes the firmware consult an AMS mapping table that does not exist without an AMS, and it pauses. Passing "" (so bpm omits the field) is also not sufficient on current firmware.
-
ams_mapping2 (per-nozzle). This must carry the correct ams_id:
- Single-nozzle printers (P2S, H2S, X1, A1, P1, …) must use
ams_id: 255 — the main/virtual tray.
- True dual-nozzle printers (H2D / H2D Pro / H2C / X2D) use
ams_id: 254 — the deputy/left nozzle fed by the external spool.
bpm hardcodes a single value that is wrong for one of these classes, which is what produces 07FF_8012.
-
H2-family field typing. H2-family firmware (H2D, H2D Pro, H2C, X2D, and the single-nozzle H2S) wants integer 0/1 — not JSON booleans — for the calibration / leveling fields (bed_leveling, flow_cali, layer_inspect, vibration_cali). X1 / P1 / A1 / P2S accept real JSON booleans. use_ams and timelapse stay boolean on all models. bpm does not differentiate.
Note on serial families: H2S shares the 094 serial + firmware family with H2D, but H2S is single-nozzle. So family detection alone is not enough — ams_id selection (254 vs 255) must be driven by nozzle count, not by firmware family.
Our workaround
We stopped calling print_3mf_file and instead build the project_file command from bpm.bambucommands.PRINT_3MF_FILE and publish it directly over MQTT. The essential parts:
import copy, json
from bpm.bambucommands import PRINT_3MF_FILE
from bpm.bambutools import PrinterSeries, getPrinterSeriesByModel
DUAL_NOZZLE_MODELS = {"h2d", "h2d pro", "h2dpro", "h2c", "x2d"}
H_FAMILY_MODELS = DUAL_NOZZLE_MODELS | {"h2s"}
cmd = copy.deepcopy(PRINT_3MF_FILE)
p = cmd["print"]
# subtask_name = basename without .3mf/.gcode
# url scheme: file:///sdcard{remote} for A1/P1, ftp://{remote} otherwise
series = getPrinterSeriesByModel(printer.config.printer_model)
p["url"] = f"file:///sdcard{remote}" if series in (PrinterSeries.A1, PrinterSeries.P1) else f"ftp://{remote}"
p["file"] = remote
p["param"] = p["param"].replace("#", "1") # single plate
p["use_ams"] = False
p["ams_mapping"] = [-1] # <-- firmware rejects raw 254/255 here
p["ams_mapping2"] = [{"ams_id": 254 if is_dual_nozzle else 255, "slot_id": 0}]
fmt = (lambda v: (1 if v else 0)) if is_h_family else (lambda v: v)
p["bed_leveling"] = fmt(bed_level)
p["flow_cali"] = fmt(flow_calibration)
p["layer_inspect"] = fmt(p["layer_inspect"])
p["vibration_cali"] = fmt(p["vibration_cali"])
p["timelapse"] = timelapse
printer.client.publish(f"device/{printer.config.serial_number}/request", json.dumps(cmd))
This starts prints reliably across our single- and dual-nozzle, with and without an AMS attached.
Suggested fix in bpm
In print_3mf_file, when use_ams=False (external spool):
- Set the flat
ams_mapping to [-1] rather than passing raw tray IDs or omitting it.
- Set
ams_mapping2 ams_id based on nozzle count: 255 for single-nozzle printers, 254 for true dual-nozzle printers — not based on serial/firmware family (H2S is single-nozzle despite the 094/H2 family).
- Encode the calibration/leveling fields (
bed_leveling, flow_cali, layer_inspect, vibration_cali) as integer 0/1 for H2-family firmware, JSON booleans otherwise.
Reproduction
- Single-nozzle Bambu printer (e.g. P2S or H2S), no AMS attached, filament on the external spool.
- Upload a single-plate
.3mf to the SD card.
- Call
print_3mf_file(name=<abs path>, plate=1, bed=PlateType.AUTO, use_ams=False, ams_mapping="", ...).
- Expected: print starts. Actual: HMS
07FF_8012 "Failed to get AMS mapping table"; print never starts.
Bug report:
bpm.print_3mf_filefails with07FF_8012 "Failed to get AMS mapping table"when printing from the external spool (no AMS)bambu-printer-manager(bpm),>=1.0.2BambuPrinter.print_3mf_file(...)07FF_8012— "Failed to get AMS mapping table".print_3mf_fileand build/publish theproject_fileMQTT command ourselves. Details below.What we expected
Calling
print_3mf_fileto print one plate of an uploaded.3mffrom the external spool (no AMS attached) should start the print.We tried what the API suggests for "no AMS":
What actually happens
The print does not start. The printer raises HMS
07FF_8012"Failed to get AMS mapping table".Root cause is how the firmware interprets the AMS mapping fields in the
project_filecommand, andbpmdoes not encode them correctly for external-spool / single-nozzle printing:ams_mapping(flat array). The firmware rejects raw tray IDs (254/255) in the flatams_mapping. For external-spool printing it must be[-1]. Passing a non-empty mapping makes the firmware consult an AMS mapping table that does not exist without an AMS, and it pauses. Passing""(so bpm omits the field) is also not sufficient on current firmware.ams_mapping2(per-nozzle). This must carry the correctams_id:ams_id: 255— the main/virtual tray.ams_id: 254— the deputy/left nozzle fed by the external spool.bpmhardcodes a single value that is wrong for one of these classes, which is what produces07FF_8012.H2-family field typing. H2-family firmware (H2D, H2D Pro, H2C, X2D, and the single-nozzle H2S) wants integer
0/1— not JSON booleans — for the calibration / leveling fields (bed_leveling,flow_cali,layer_inspect,vibration_cali). X1 / P1 / A1 / P2S accept real JSON booleans.use_amsandtimelapsestay boolean on all models.bpmdoes not differentiate.Our workaround
We stopped calling
print_3mf_fileand instead build theproject_filecommand frombpm.bambucommands.PRINT_3MF_FILEand publish it directly over MQTT. The essential parts:This starts prints reliably across our single- and dual-nozzle, with and without an AMS attached.
Suggested fix in
bpmIn
print_3mf_file, whenuse_ams=False(external spool):ams_mappingto[-1]rather than passing raw tray IDs or omitting it.ams_mapping2ams_idbased on nozzle count:255for single-nozzle printers,254for true dual-nozzle printers — not based on serial/firmware family (H2S is single-nozzle despite the094/H2 family).bed_leveling,flow_cali,layer_inspect,vibration_cali) as integer0/1for H2-family firmware, JSON booleans otherwise.Reproduction
.3mfto the SD card.print_3mf_file(name=<abs path>, plate=1, bed=PlateType.AUTO, use_ams=False, ams_mapping="", ...).07FF_8012"Failed to get AMS mapping table"; print never starts.