Files
bambuddy/backend
maziggy 70ee53464d Say why an upload failed instead of blaming the SD card (issue #2899)
Every dispatch upload that failed carried one sentence: "Failed to
upload file to printer. Check if SD card is inserted and properly
formatted (FAT32/exFAT)." The reporter got it after a TLS handshake
failure and restarted the printer on the strength of it. That could not
have helped. The handshake never reached the printer's filesystem, and
the cool-off that made the next dispatch fail the same way lives in
Bambuddy's own memory, where power-cycling a printer does not reach.

because the advice was known not to work. It survived in the string
people actually read, so the failure mode that fix closed was still
reachable through the UI.
reachable through the UI.

The information was never missing. connect() separates five failure
classes and upload_file() separates 553/552/550, each with its own log
line -- 553 even logs a spelled-out list of storage causes -- and then
both returned a bare False. The dispatch had nothing left to work with
and guessed storage for all of them.

So the reason now travels with the result. The client records an
FtpFailure (kind, detail, and the reply code where the server gave one)
on every failure branch, and upload_file_async fills in a report object
the CALLER owns. Not a per-IP dict beside _mode_cache: those describe a
printer and are right to share, while this describes one operation, and
a background timelapse fetch running beside a dispatch would overwrite
the dispatch's reason with its own -- reporting the wrong cause with
total confidence, which is this bug again rather than a fix for it.

describe_upload_failure() picks the wording, and lives next to the kinds
so the two cannot drift. A 553 or 552 keeps the card advice, which is
the case it was written for, and quotes the reply code so a queue entry
and a support bundle line up. A handshake failure says the file service
answered without TLS and that the card is not involved. A refusal points
at the access code, a timeout at the network, and anything unclassified
says so and points at the log rather than picking a plausible cause. A
wrong instruction costs more than a vague one: it sends someone to work
on hardware that is fine. Nothing prescribes a power cycle.

The failure notification now carries the same sentence the queue shows,
instead of its own fixed "Failed to upload file to printer", so a push
and the screen cannot disagree about what happened.

Tests cover the classification, the report reaching the caller through
the retry loop, two callers not crossing, the queue entry itself, and
one line per message branch -- without that last one, deleting the
access-code or timeout branch left every other assertion passing, since
they only check that the card is not named and the generic message
satisfies that too. The card-advice test keys on the instruction rather
than the words "SD card", because the handshake message names the card
in order to rule it out.
2026-08-22 10:26:12 +02:00
..