Context
#100 adds a retry policy to the direct .NET archive downloader, but exceptions raised through PowerShell method invocation do not match the current transient-exception checks.
Observed behavior
Invoke-NerdFontDownload checks the outer exception for HttpRequestException, IOException, or OperationCanceledException. PowerShell wraps failures from .GetResult() and related .NET calls in MethodInvocationException, so transient network and timeout failures bypass the retry loop.
A local endpoint that accepted a connection without returning headers, combined with -AttemptTimeoutSeconds 1, failed after 1.05 seconds. The exception chain was MethodInvocationException -> TaskCanceledException -> TaskCanceledException -> IOException -> SocketException; no retry occurred.
Expected behavior
Transient HTTP, stream, I/O, and timeout failures use the configured retry policy. Non-transient failures such as HTTP 404 fail immediately.
Reproduction
- Run
Invoke-NerdFontDownload against an endpoint that accepts a connection but does not return headers.
- Set
AttemptTimeoutSeconds to 1.
- Observe that the call fails after the first timeout rather than retrying.
Environment
PowerShell 7.6.5 on Windows. The exception-wrapping behavior is part of PowerShell method invocation and is not expected to be OS-specific.
Regression
Introduced by the direct .NET downloader in #100. The earlier Invoke-WebRequest implementation supplied retry behavior through cmdlet parameters.
Workaround
Run Install-NerdFont again manually after a transient failure.
Acceptance criteria
- Wrapped exception chains are classified using the underlying transient exception.
- Transient request, timeout, streaming, and file I/O failures retry according to the configured count and delay.
- HTTP 408, 429, and 5xx responses continue to retry.
- HTTP 404 and other non-transient failures continue to fail immediately.
- Temporary files and disposable resources are cleaned up after every failed attempt.
Technical decisions
Keep exception classification bounded to known transient types and inspect inner exceptions without broadly retrying unrelated failures.
Implementation plan
Context
#100 adds a retry policy to the direct .NET archive downloader, but exceptions raised through PowerShell method invocation do not match the current transient-exception checks.
Observed behavior
Invoke-NerdFontDownloadchecks the outer exception forHttpRequestException,IOException, orOperationCanceledException. PowerShell wraps failures from.GetResult()and related .NET calls inMethodInvocationException, so transient network and timeout failures bypass the retry loop.A local endpoint that accepted a connection without returning headers, combined with
-AttemptTimeoutSeconds 1, failed after 1.05 seconds. The exception chain wasMethodInvocationException -> TaskCanceledException -> TaskCanceledException -> IOException -> SocketException; no retry occurred.Expected behavior
Transient HTTP, stream, I/O, and timeout failures use the configured retry policy. Non-transient failures such as HTTP 404 fail immediately.
Reproduction
Invoke-NerdFontDownloadagainst an endpoint that accepts a connection but does not return headers.AttemptTimeoutSecondsto1.Environment
PowerShell 7.6.5 on Windows. The exception-wrapping behavior is part of PowerShell method invocation and is not expected to be OS-specific.
Regression
Introduced by the direct .NET downloader in #100. The earlier
Invoke-WebRequestimplementation supplied retry behavior through cmdlet parameters.Workaround
Run
Install-NerdFontagain manually after a transient failure.Acceptance criteria
Technical decisions
Keep exception classification bounded to known transient types and inspect inner exceptions without broadly retrying unrelated failures.
Implementation plan