Files
PSProxmoxVE/docs/decisions/0004-no-bare-catch-blocks.md
T
goodolclint-claude[bot] b90791e2bf docs: migrate DECISIONS.md to house-format ADRs, and retire the review folder (#131)
D001-D021 become ADR 0001-0021 in docs/decisions/, one decision per file.
D017's PESTER_VERSION amendment was a second decision in one entry and becomes
ADR 0022. ADR 0023 records the migration and reverses the lane2-change-plan
ruling that deliberately kept DECISIONS.md until the CI lane work landed.

DECISIONS.md is reduced to a stub with a D-to-ADR redirect table, so the four
released CHANGELOG entries and older issue bodies that cite it degrade to a
redirect rather than a dead reference.

docs/review/ and docs/lane2-change-plan.md are deleted (ADR 0024). Of 91
findings, 83 were resolved and six of the seven still open were already GitHub
issues; F021 was the exception and is now #130.

CLAUDE.md's Key Conventions list gains the two rules it was missing and becomes
the checklist, with the ADRs carrying rationale.
2026-09-02 14:49:07 +00:00

1.6 KiB

ADR 0004 — No bare catch blocks

  • Status: Accepted
  • Date: 2026-03-22
  • Deciders: unrecorded; adopted during review scan 2026-03-22
  • Context source: docs/review/findings.json F039

Context

Bare catches in PveHttpClient, PveCmdletBase, VmService, ContainerService and GetPveVmCmdlet swallowed every error, including ones that had nothing to do with the transient failure the catch was written for. A misconfigured endpoint and a stalled task presented identically: as silence.

Decision

No catch { } and no unfiltered catch (Exception) { }. Every catch either names a specific exception type, or filters with a when clause that excludes fatal exceptions.

catch (PveApiException ex) { WriteWarning(ex.Message); }

catch (Exception ex) when (ex is not OutOfMemoryException and not StackOverflowException)
{
    WriteVerbose($"Status poll failed: {ex.Message}");
}

Rejected alternatives

Catching everything and continuing, on the theory that a status poll failing is never worth surfacing:

try { ... }
catch { }

try { ... }
catch (Exception) { /* ignore */ }

Rejected because it also swallows OutOfMemoryException and StackOverflowException, and because "this particular call is allowed to fail quietly" is a claim that has to be re-checked whenever the body of the try grows.

Consequences

Filtered catches still need somewhere for the message to go — WriteVerbose at minimum — or the filter merely moves the silence. This regressed once: F039 was reopened after bare catches reappeared in VmService.PingGuestAgent and Import-PveOva's VM-retrieval fallback, and was fixed again.