Skip to content

feat: Retry WSANO_DATA DNS errors and surface recovery guidance#45

Merged
tablackburn merged 3 commits into
mainfrom
feature/transient-dns-no-data-retry
Apr 29, 2026
Merged

feat: Retry WSANO_DATA DNS errors and surface recovery guidance#45
tablackburn merged 3 commits into
mainfrom
feature/transient-dns-no-data-retry

Conversation

@tablackburn
Copy link
Copy Markdown
Owner

@tablackburn tablackburn commented Apr 28, 2026

Summary

  • Broaden the transient-error regex in Invoke-PatApi to retry the Windows WSANO_DATA (11004) socket error — "The requested name is valid, but no data of the requested type was found." — which can occur when DNS records are propagating or when only AAAA records are returned. Previously this error fell through the existing exponential-backoff retry (1s/2s/4s) and surfaced immediately.
  • After retries are exhausted on a DNS-class failure, throw a single actionable message naming Resolve-DnsName, Test-NetConnection, Get-PatStoredServer, and Add-PatServer -Force as concrete recovery steps. This mirrors the existing 401-token-recovery pattern and replaces the raw socket error wrapped through three cmdlet layers (e.g. Update-PatLibraryGet-PatLibraryInvoke-PatApi). The original error is preserved at the end for diagnostics.
  • Add 4 unit tests covering: WSANO_DATA retry-and-succeed, DNS guidance after exhaustion, WSANO_DATA guidance after exhaustion, and a negative test confirming non-DNS transient errors (503) still receive the generic message.

Motivation

A user hit WSANO_DATA mid-session and saw a confusing three-layer error:

Failed to resolve section name: Failed to get Plex library information:
Error invoking Plex API: The requested name is valid, but no data of the
requested type was found. (plex.domain.com:port)

The error self-resolved on the next attempt, confirming it was transient — but the existing regex 'No such host|DNS|name.+not.+resolve' did not match the WSANO_DATA wording, so the retry path was never engaged.

Test Plan

  • pwsh -Command "Set-BuildEnvironment -Force; Invoke-Pester -Path tests/Unit/Private/Invoke-PatApi.tests.ps1" — 57/57 pass (4 new)
  • CI runs full test + coverage suite

Verified 2026-05-10: PR head c17fbfb green — CI run 25084381184 success; check-runs for c17fbfb show Unit Tests (ubuntu/macOS/windows + Windows PS5.1) all success, Integration Tests (windows + ubuntu) success, PSScriptAnalyzer Lint success, codecov/patch success.

Breaking Changes

None.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • DNS-related failures on Windows (including WSANO_DATA / "no data of the requested type") are now treated as transient and retried with exponential backoff.
    • After DNS retries are exhausted, users receive a single, clear recovery message listing concrete remediation commands instead of raw socket errors.
  • Tests

    • Added unit tests covering WSANO_DATA retry behavior and DNS guidance on retry exhaustion.
  • Chores

    • Module version updated to 0.11.2 and changelog entry added.

- Broaden the transient-error regex in Invoke-PatApi to retry the Windows
  WSANO_DATA (11004) socket error ("no data of the requested type"),
  which can occur when DNS records are still propagating or when only
  AAAA records are returned.
- After retries are exhausted on a DNS-class failure, throw a single
  actionable message naming Resolve-DnsName, Test-NetConnection,
  Get-PatStoredServer, and Add-PatServer -Force as recovery steps,
  mirroring the existing 401 token-recovery pattern. Original error is
  preserved for diagnostics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 28, 2026 17:55
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 58c66599-a91a-4abf-aaaf-2f49e9dda750

📥 Commits

Reviewing files that changed from the base of the PR and between 155449f and c17fbfb.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • PlexAutomationToolkit/PlexAutomationToolkit.psd1
✅ Files skipped from review due to trivial changes (1)
  • PlexAutomationToolkit/PlexAutomationToolkit.psd1

📝 Walkthrough

Walkthrough

Invoke-PatApi classifies Windows WSANO_DATA (11004) as a transient DNS condition so it participates in exponential-backoff retries, and after retries exhaust it surfaces a single, actionable DNS-resolution guidance message (naming specific cmdlets) instead of emitting the raw socket error.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Added 0.11.2 Unreleased entry documenting WSANO_DATA retry classification and consolidated DNS remediation guidance after retry exhaustion.
DNS Error Handling
PlexAutomationToolkit/Private/Invoke-PatApi.ps1
Centralized DNS error pattern matching (including Windows “no data of the requested type”), classify WSANO_DATA as transient for exponential-backoff retries, and throw a single actionable DNS-resolution guidance message (with specific cmdlets and original error text) when retries are exhausted.
Tests
tests/Unit/Private/Invoke-PatApi.tests.ps1
Added unit tests verifying WSANO_DATA is treated as transient (succeeds on retry), DNS guidance is produced after MaxRetries (including original error), WSANO_DATA follows DNS guidance path, and non-DNS transient errors do not trigger DNS guidance.
Manifest
PlexAutomationToolkit/PlexAutomationToolkit.psd1
Bumped ModuleVersion from 0.11.1 to 0.11.2.

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Caller (Invoke-PatApi)
    participant Retry as Retry Logic
    participant DNS as DNS Resolver
    participant Plex as Plex API
    Caller->>Retry: Invoke request
    Retry->>DNS: Resolve host (may return WSANO_DATA / DNS error)
    alt DNS resolved
        DNS->>Plex: Connect and send API request
        Plex-->>Caller: API response
    else Transient DNS error (WSANO_DATA)
        Retry-->>Caller: wait/backoff, retry
        Retry->>DNS: Resolve host (retry)
        alt Success on retry
            DNS->>Plex: Connect and send API request
            Plex-->>Caller: API response
        else Retries exhausted
            DNS-->>Caller: Consolidated DNS remediation guidance (Resolve-DnsName, Test-NetConnection, Get-PatStoredServer, Add-PatServer -Force) with original error text
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped where DNS whispers hide,
WSANO_DATA said "try again, dear friend",
I counted backoffs and nudged the retry,
Then gifted cmdlets to mend the line—Resolve, Test, Add—
A tiny hop, a clearer path along the net.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main changes: retrying WSANO_DATA DNS errors and adding recovery guidance, which aligns perfectly with the primary objectives of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/transient-dns-no-data-retry

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the resilience and usability of the internal Plex API wrapper (Invoke-PatApi) by retrying an additional Windows DNS-related socket error (WSANO_DATA / 11004) and, when retries are exhausted for DNS-class failures, throwing a single actionable recovery message instead of propagating layered/raw socket errors.

Changes:

  • Expand transient DNS error detection to include the Windows WSANO_DATA (“no data of the requested type”) wording so it participates in the retry loop.
  • Add a DNS-specific “recovery guidance” error message when DNS-class transient retries are exhausted (while preserving the original error text for diagnostics).
  • Add unit tests covering WSANO_DATA retry success, DNS guidance on exhaustion (including original error preservation), and ensuring non-DNS transient errors still use the generic message.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
PlexAutomationToolkit/Private/Invoke-PatApi.ps1 Broaden DNS transient detection and add DNS-specific actionable error after retry exhaustion.
tests/Unit/Private/Invoke-PatApi.tests.ps1 Add Pester coverage for WSANO_DATA retry behavior and DNS guidance messaging.
CHANGELOG.md Document the new retry signature and the improved DNS failure messaging.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread PlexAutomationToolkit/Private/Invoke-PatApi.ps1 Outdated
Comment thread PlexAutomationToolkit/Private/Invoke-PatApi.ps1 Outdated
Comment thread CHANGELOG.md Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
PlexAutomationToolkit/Private/Invoke-PatApi.ps1 (1)

151-163: Consider centralizing the DNS match pattern.

The retry predicate and the final remediation branch now rely on the same message list in two places. Extracting it once would keep the retry classification and the surfaced guidance from drifting apart later.

♻️ Possible cleanup
+    $dnsTransientPattern = 'No such host|DNS|name.+not.+resolve|no data of the requested type'
+
     function Test-TransientError {
         param([System.Management.Automation.ErrorRecord]$ErrorRecord)
@@
-        if ($message -match 'No such host|DNS|name.+not.+resolve|no data of the requested type') {
+        if ($message -match $dnsTransientPattern) {
             return $true
         }
@@
-                    if ($errorMessage -match 'No such host|DNS|name.+not.+resolve|no data of the requested type') {
+                    if ($errorMessage -match $dnsTransientPattern) {
                         throw ("Plex API request failed after $MaxRetries attempts: DNS could not resolve the server hostname. " +
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@PlexAutomationToolkit/Private/Invoke-PatApi.ps1` around lines 151 - 163,
Extract the DNS error regex into a single named variable (e.g.,
$DnsErrorPattern) at the top of the Invoke-PatApi function or module scope and
replace the inline pattern in the remediation branch (the -match against
$errorMessage inside the if ($isTransient -and $attempt -eq $MaxRetries) block)
and the retry predicate that classifies transient DNS/connection failures to use
that variable instead; ensure the variable uses the same regex options
(case-insensitive) and is referenced wherever the current hard-coded 'No such
host|DNS|name.+not.+resolve|no data of the requested type' pattern is repeated
so both classification and user guidance remain in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@PlexAutomationToolkit/Private/Invoke-PatApi.ps1`:
- Around line 151-163: Extract the DNS error regex into a single named variable
(e.g., $DnsErrorPattern) at the top of the Invoke-PatApi function or module
scope and replace the inline pattern in the remediation branch (the -match
against $errorMessage inside the if ($isTransient -and $attempt -eq $MaxRetries)
block) and the retry predicate that classifies transient DNS/connection failures
to use that variable instead; ensure the variable uses the same regex options
(case-insensitive) and is referenced wherever the current hard-coded 'No such
host|DNS|name.+not.+resolve|no data of the requested type' pattern is repeated
so both classification and user guidance remain in sync.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c3468a0f-c903-43de-965a-d136404e973f

📥 Commits

Reviewing files that changed from the base of the PR and between 85f9e27 and 6d10deb.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • PlexAutomationToolkit/Private/Invoke-PatApi.ps1
  • tests/Unit/Private/Invoke-PatApi.tests.ps1

- Extract the DNS error regex into a single $dnsErrorPattern variable
  used by both Test-TransientError and the post-exhaustion guidance
  branch, so the retry classification and the surfaced guidance cannot
  drift if either pattern is widened later (CodeRabbit, Copilot nit).
- Tighten the comment on the post-exhaustion branch to clarify that
  only DNS resolution failures get the actionable message; timeouts
  and connection-refused remain transient but fall through to the
  generic message because they have a different recovery story
  (Copilot nit).
- Reword the CHANGELOG entry as two bullets to avoid implying that
  multiple new retry conditions were added when only one (WSANO_DATA)
  was (Copilot nit).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Roll up the WSANO_DATA retry classification and DNS post-exhaustion
guidance changes from this branch into a release. Bump ModuleVersion
0.11.1 -> 0.11.2 (PATCH; ### Changed-only refinements, no public API
changes), and convert the [Unreleased] section in CHANGELOG.md into
the dated [0.11.2] section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tablackburn tablackburn merged commit 6f159f9 into main Apr 29, 2026
15 checks passed
@tablackburn tablackburn deleted the feature/transient-dns-no-data-retry branch April 29, 2026 03:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants