Skip to content

[Enhancement]: Cross-app — 39 unfiltered catch (Exception) blocks and 17 silent catches, with no guard #2615

Description

@laurentiu021

Problem

The project's own rule is specific exception types only, and an empty catch at least logs at Debug. Today, outside the three in App.xaml.cs, each of which says why it is broad, the app has 39 catch (Exception …) blocks with no when filter, and 17 typed catches with an empty body. Some are there on purpose and say so (LibreHardwareMonitor and NvAPI can throw anything from native code, and ViewModelBase.InitializeAsync is the last-resort net), but nothing tells those apart from the rest, and no test stops a new one.

  • Unfiltered catch (Exception): Services/EtwBandwidthSource.cs, GamingProfileService.cs (3), PingMonitorService.cs, ResourceHistoryService.cs (3), TemperatureService.cs (5), ThemeService.cs (2), TrayIconService.cs (2), UpdateService.cs, ViewModels/AudioMixerViewModel.cs (2), BandwidthMonitorViewModel.cs, BulkInstallerViewModel.cs (3), DashboardViewModel.cs (8), DnsHostsViewModel.cs (4), ProcessManagerViewModel.cs, StandbyMemoryViewModel.cs, ViewModelBase.cs.
  • Empty typed catches: Helpers/AtomicFile.cs, Helpers/ExplorerShell.cs, Services/AudioMixerService.cs (2), AudioPolicyConfig.cs, GamingProfileService.cs, LargeFileScanner.cs (6), PowerShellRunner.cs (2), ServiceManagerService.cs, ViewModels/DnsHostsViewModel.cs (2).

Proposed solution

Go through each: narrow it to the types the call can throw, or keep it broad with a when filter or a one-line reason where the code wraps native or third-party code that can throw anything. Empty catches log at Debug. Then add an ArchitectureTests guard that fails on a new unfiltered catch (Exception) or empty catch, with the reviewed ones listed by file and reason, so the list only shrinks.

Affected tab

Cross-app

Activity

  1. laurentiu021 commented on Oct 9, 2026

    @laurentiu021
    OwnerAuthor

    Fixed in #2664.

    Empty catches. Fifteen had nothing in their body when I got to this: three of the 17 above went with the code around them in #2638 and #2651, and SpeedTestService had one with a when filter that the count missed. The one in GamingProfileService could not run (Process.Exited's remove accessor does not throw, whatever state the process is in) and is gone. The other fourteen say why in a comment rather than logging, because each is an expected case in a cleanup or a scan's inner loop (a process that had already exited, a tab closing, a folder the scan cannot list), and that is how the app's other deliberate swallows already read.

    Unfiltered catch (Exception). Two are narrowed to what their call throws: PingMonitorService, where Ping hands back a failed lookup or send as PingException, and ThemeService.Save (IOException, UnauthorizedAccessException). The other 37 stay broad, with App.xaml.cs's three and the two catch blocks with no type that release what they built and rethrow, and each of those 42 now says why beside the code. UpdateService.GetLatestAsync is one of them: reading the body fails as an IOException, an InvalidDataException or an InvalidOperationException as well as a JsonException, and its sibling GetRecentAsync catches only the last, which is #2663.

    What holds it. ArchitectureTests.EveryCatch_SaysWhy_AndTheBroadOnesAreTheReviewedOnes fails the build on an empty catch body, on a catch of everything with no comment directly above it or first in its body, and on any file whose number of those is not the reviewed one, so the list only shrinks. CONTRIBUTING's "No silent failures" describes the rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions