Fix firmware flash reporting success when it actually failed#190
Conversation
The local-file / by-SoC / dropdown firmware upgrade paths all funnel through PerformSysupgradeAsync, which wrapped upload + size-verification + sysupgrade in a try/catch that only logged the error and returned normally. The caller (UpgradeFirmwareFromFileAsync) then unconditionally set ProgressValue = 100 and showed "Upgrade Complete!! Device has been flashed!" — so a failed flash looked identical to a successful one and the device was left on its old firmware. UploadFileAsync had the same swallow, so even a failed SCP upload returned as success. This is especially likely on dropbear targets where the Renci.SshNet ScpClient upload can fail/truncate: the upload silently no-ops, the device never gets the files, and the UI still claims success. Changes: - SshClientService.UploadFileAsync: rethrow instead of swallowing, so a failed upload surfaces to the caller. - SysUpgradeService.PerformSysupgradeAsync: rethrow after logging so the caller can tell a failed flash from a successful one; add UploadAndVerifyWithRetryAsync which retries the upload + on-device size check (3 attempts) before giving up, so flaky links recover instead of silently proceeding against a missing file. - FirmwareTabViewModel.UpgradeFirmwareFromFileAsync: show an explicit "Upgrade failed" dialog when the upgrade throws, instead of silently doing nothing. Build clean (0 errors); all 60 existing tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Rebased mentally against current Since this PR went up, The problem is that the signal never escapes. Every one of those new throws lands in the outer catch (Exception ex)
{
_logger.Error(ex, "Error during sysupgrade.");
updateProgress($"Error: {ex.Message}");
// no rethrow
}and ProgressValue = 100;
SetProgressBarBrush(ProgressCompleteBrush);
var result = await _messageBoxService.ShowCustomMessageBox(
"Upgrade Complete!!",
$"Device has been flashed!\n\n...",So today Companion can detect that the flash failed, discard that fact, and still tell the user "Device has been flashed!" — the new validators are effectively dead code in the failure path. A completely failed flash remains pixel-identical to a successful one. This is not hypothetical. It's why testers flash via the Local-file flow, see the green "Upgrade Complete", and stay on their old firmware — then spend days debugging a device they believe was reflashed. This PR is small and does exactly one thing: let the failure reach the user. Rethrow at the three swallow points, retry-with-verify on the upload, and show a real "Upgrade failed — the device is still on its previous firmware" dialog. Build is green, Related, for context: OpenIPC/firmware#2220 fixes the underlying Happy to rebase or split this further if that makes review easier. |
|
Retargeted this PR to Validation against current
The README and |
|
Thank you for merging this, and for retargeting it to One small question, asked with no expectation and entirely at your discretion: is a release cut from The only reason I ask is that this particular fix is one whose value is fully in users' hands and zero in the repo. So: no pressure at all, and I'm not asking you to rush |
Problem
A failed firmware flash is reported to the user as a success. The device is left on its old firmware while the UI shows 100% and "Upgrade Complete!! Device has been flashed!"
Root cause is a chain of swallowed exceptions:
Especially easy to hit on dropbear cameras where the Renci.SshNet ScpClient upload can fail/truncate: upload silently no-ops, device never gets the files, UI still claims success (unchanged GITHUB_VERSION banner, no rootfs change).
Fix
Testing