Browse Source

Fix queue prints failing with SD card error on A1 printers

Queue prints were uploading files to /cache/ directory but the MQTT
print command referenced files by name only (ftp://{filename}), which
resolves to the root directory. The printer couldn't find the file,
causing "MicroSD Card read/write exception error".

Changes:
- Upload queue prints to root / instead of /cache/ (matches reprint)
- Add filename cleaning for .gcode.3mf double extensions
- Pre-delete existing files before upload to avoid FTP 553 errors
- Fix misleading docstring in bambu_mqtt.py

Fixes #86
maziggy 4 months ago
parent
commit
03f4f8436a
3 changed files with 34 additions and 4 deletions
  1. 10 0
      CHANGELOG.md
  2. 1 1
      backend/app/services/bambu_mqtt.py
  3. 23 3
      backend/app/services/print_scheduler.py

+ 10 - 0
CHANGELOG.md

@@ -2,6 +2,16 @@
 
 All notable changes to Bambuddy will be documented in this file.
 
+## [0.1.6b13] - 2026-01-16
+
+### Fixed
+- **Queue prints failing on A1 printers** - Fixed "MicroSD Card read/write exception error" when starting prints from queue:
+  - Root cause: Queue uploaded files to `/cache/` but print command referenced root `/`
+  - Queue now uploads to root directory like archive reprint does
+  - Added filename cleaning (handles `.gcode.3mf` double extensions)
+  - Added pre-delete of existing files to avoid FTP 553 errors
+  - Fixes [#86](https://github.com/maziggy/bambuddy/issues/86)
+
 ## [0.1.6b12] - 2026-01-16
 
 ### Added

+ 1 - 1
backend/app/services/bambu_mqtt.py

@@ -1941,7 +1941,7 @@ class BambuMQTTClient:
     ):
         """Start a print job on the printer.
 
-        The file should already be uploaded to /cache/ on the printer via FTP.
+        The file should already be uploaded to the printer's root directory via FTP.
 
         Args:
             filename: Name of the uploaded file

+ 23 - 3
backend/app/services/print_scheduler.py

@@ -13,7 +13,7 @@ from backend.app.models.archive import PrintArchive
 from backend.app.models.print_queue import PrintQueueItem
 from backend.app.models.printer import Printer
 from backend.app.models.smart_plug import SmartPlug
-from backend.app.services.bambu_ftp import get_ftp_retry_settings, upload_file_async, with_ftp_retry
+from backend.app.services.bambu_ftp import delete_file_async, get_ftp_retry_settings, upload_file_async, with_ftp_retry
 from backend.app.services.printer_manager import printer_manager
 from backend.app.services.tasmota import tasmota_service
 
@@ -268,12 +268,32 @@ class PrintScheduler:
             return
 
         # Upload file to printer via FTP
-        remote_filename = archive.filename
-        remote_path = f"/cache/{remote_filename}"
+        # Use a clean filename to avoid issues with double extensions like .gcode.3mf
+        base_name = archive.filename
+        if base_name.endswith(".gcode.3mf"):
+            base_name = base_name[:-10]  # Remove .gcode.3mf
+        elif base_name.endswith(".3mf"):
+            base_name = base_name[:-4]  # Remove .3mf
+        remote_filename = f"{base_name}.3mf"
+        # Upload to root directory (not /cache/) - the start_print command references
+        # files by name only (ftp://{filename}), so they must be in the root
+        remote_path = f"/{remote_filename}"
 
         # Get FTP retry settings
         ftp_retry_enabled, ftp_retry_count, ftp_retry_delay, ftp_timeout = await get_ftp_retry_settings()
 
+        # Delete existing file if present (avoids 553 error on overwrite)
+        try:
+            await delete_file_async(
+                printer.ip_address,
+                printer.access_code,
+                remote_path,
+                socket_timeout=ftp_timeout,
+                printer_model=printer.model,
+            )
+        except Exception:
+            pass  # File may not exist, that's fine
+
         try:
             if ftp_retry_enabled:
                 uploaded = await with_ftp_retry(