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.
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.jsonF039
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.