Skip to content

PowerShell installer must never terminate ungracefully — always show the user a clean 'what happened' #577

Description

@shujaatTracebloc

Filed from a field install on a restricted corporate network. Companion issues: log-hygiene (no info leak) and network-resilience.

Problem statement

When the install fails, PowerShell must never terminate ungracefully. Today it dies with a raw terminating-error dump — stack, source line, PS>TerminatingError() — leaving the user with a scary crash and no idea what happened or what to do. The user should always see a clean, human explanation of what happened during the installation and the exact next step; the window/session should never just die on them.

Observed (the field log):

PS>TerminatingError(): "cosign signature verification FAILED for manifest.sha256 -- refusing to install."
+ & $cosign @cosignArgs 2>$null 1>$null
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (...) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError

Explanation (root cause)

The installer's failure paths are bare throws (and unhandled native-command stderr) with no try/catch around main(). An unhandled terminating error makes PowerShell print the raw error and end the script. There is no graceful closer, no classification of fatal vs recoverable, and no guaranteed "here's your log / here's what to do" message. So a network hiccup surfaces as a crash instead of a diagnosis.

Proposed solution

  1. A single top-level try / catch / finally (+ trap) in the bootstrap and the main installer. The catch renders one clean, branded block — what failed, why in plain terms, the exact next steps, and where the log is — then exit <code>. No stack, no source line, ever.
  2. Classify failures fatal vs recoverable. Optional/recoverable steps warn and continue (the GPU-toolkit timeout already does this correctly — "GPU not set up, continuing in CPU mode"). Only a genuine can't-proceed stops — and stops cleanly. Apply that pattern consistently.
  3. Every native call bounded + exit-code-checked (the installer already has Invoke-Bounded / Wait-ProcessWithDeadline; the raw & $cosign at line 360 was the one that slipped through and became a crash). A wedged or erroring tool becomes a handled condition, never a terminating error.
  4. A guaranteed finally that always prints "Log saved to … — send it to support if you're stuck" and stops the transcript cleanly, so the window never just disappears.

This is the substrate the other two issues rely on: it's what converts a network block into "your network is blocking X — here's what to do" instead of a stack dump.
Severity: Tier 1 — UX / trust. Confidence: CONFIRMED.

Metadata

Metadata

Labels

devopsDevOps / CI-CD / build & deploypriorityNeeds attention before other workwork-type:bugDefect or regression

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions