Windows 11 Release Guard

Troubleshooting

Use this when a check fails, a source degrades, or a local Windows result looks surprising.


CHECK_INCOMPLETE

CheckWhat to do
source_statusConfirm whether live remote, cache, bundled, or unavailable source was used.
source_problemsRead exact fetch, parse, signature, hash, or freshness problem.
policy_signature_statusVerify signature and key trust.
Strict modeConfirm live signed remote JSON is fresh enough.
python -m win11_release_guard --check-policy-source
python -m win11_release_guard --diagnose-config

Public Pages Check Fails

CheckWhat to do
Landing pageVerify dashboard URL returns expected static HTML.
Policy/signatureVerify policy bytes and signature metadata.
Manifest hashCompare manifest hash with policy bytes.
API aliasesConfirm /api/v1 files exist and match expected contract.
FreshnessCheck generated epoch and 14/45-day thresholds.
python -m win11_release_guard --check-public-pages

Local Device Label Looks Wrong

CheckWhat to do
Build familyTrust build-family mapping over display label.
Raw labelsKeep raw ProductName, Caption, and DisplayVersion for admin review.
Conflict flagsLook for LOCAL_PRODUCT_NAME_STALE, LOCAL_CAPTION_STALE, or display-version conflict flags.
Policy mapConfirm signed policy knows the build family.
python -m win11_release_guard --json-pretty --no-wua

WUA Does Not Offer Target Feature Update

CheckWhat to do
Policy verdictKeep the signed policy verdict.
WUA availabilityEnable WUA only for diagnostics.
WUfB / WSUSCheck target-release pins, WSUS/SCCM source, deferrals.
Pending rebootReview read-only pending reboot evidence.
Panther/setup logsReview fixed-path, bounded setup diagnostic tails; collection also has a generous total guard.

Panther/setup logs are administrator troubleshooting evidence only. They never decide compliance or override the signed public policy verdict. Default JSON keeps raw Panther content compacted; raw bounded tails are restored only with --include-raw-local-diagnostics.

python -m win11_release_guard --json-pretty --wua --include-raw-local-diagnostics

Generator Fails After Microsoft Page Change

CheckWhat to do
Parser eventInspect source_diagnostics.events.
HeadersCompare Release Health table headings with fixtures.
26H1 noteConfirm special/new-devices-only text is still detected.
B baselineConfirm broad target has a B-release baseline.
Servicing index missing/unparseableservicing_toc_missing, servicing_toc_parse_failed, or servicing_toc_no_usable_entries warning. Release Health still drives the policy; preview/out-of-band classification and drift context stay incomplete until the servicing index is available and carries at least one titled, hrefed row (a KB in the title is not required).
Servicing support hrefUse only safe links to https://support.microsoft.com article paths. Safe :443, query, or fragment variants canonicalize to scheme/host/path; unsafe ports, feed/API/search/download/static/traversal paths, and non-support hosts reject. If a servicing entry's KB row lacks a safe Support article href, keep the Source Diagnostic evidence (atom_support_article_href_missing); do not add a /help/<KB> fallback resolver.
Servicing row matchingIf the same KB appears more than once, confirm Release History enrichment selected a row-build match before accepting KB-only metadata. Ambiguous KB-only fallbacks should be skipped rather than silently choosing the first entry.
Support article mismatchIf Support article KB, build, URL, or parseable Applies to evidence disagrees with the servicing entry, trust the servicing entry's KB/build/release and exact MSRC KB evidence; treat Support-derived summary/security wording as untrusted. Use applies_to_releases when present to see which release values were parsed.
Security classificationUse exact MSRC CVRF KB-token evidence or validated explicit Support article wording; do not infer security status from generic servicing entry title text or KB substrings embedded in larger tokens. Exact-KB remediations count even when optional CVE/severity/product fields are absent.
pytest -q tests/test_remote_policy.py tests/test_policy_generator.py

Latest Observed Is Newer Than Latest Build

CheckWhat to do
latest_buildTreat it as the Release Health Current Versions table value.
latest_observed_buildTreat it as informational public Microsoft evidence, often from Support articles linked in the servicing table-of-contents JSON.
required_baseline_buildKeep this as the signed quality baseline used for verdicts.

A newer latest-observed build can explain why a local machine is ahead of the normal fleet baseline. It does not make the device noncompliant and does not raise the required baseline unless the policy baseline rules select that build. When Release Health has caught up and the baseline rules select that same build, all three fields can legitimately show the same build number.

Baseline Update Notice Appears

CheckWhat to do
Required baseline sourceConfirm the row is a real non-preview, non-OOB Release Health B-release.
Notice timingCheck official_release_date, official_release_precision, visible_from_utc, and visible_until_utc; date-only Microsoft evidence is intentionally labeled date-only.
Evidence statusIf Support or MSRC evidence is degraded/unknown, keep the notice but do not treat Support text as security proof.
Expired noticeExpired or inactive notice metadata should not fetch optional Support/MSRC enrichment just to decorate stale history. A stale static page hides the notice and reflows the operational panels.
Issue syncLeave it dashboard-only; the required_baseline_matched_latest_observed notice must not create or reopen GitHub Issues.

The notice explains that the compliance floor has caught up to already observed public Microsoft evidence. It is informational UI generated from local policy facts and validated public evidence; it does not change signed verdicts, required-baseline selection, runtime client behavior, or /api/v1 aliases.

On-Disk State

CheckWhat to do
cache_write_failed source problemThe state or --cache-file write was skipped or failed; the run continues on the freshly verified remote policy and the verdict and exit code are unchanged. The problem message names the path and reason.
Two instances at once (WinError 32)First cause to rule out: two runs with the same configuration share one staging file name and one raced the other's os.replace. The loser records cache_write_failed and moves on; no data is lost.
--cache-file under a missing parentThe write primitive never creates directories, so a --cache-file whose parent directory does not exist is skipped, not created. The run records cache_write_failed and caches nothing, and the embedder-only cache.save_policy_cache and wu_offer_probe.store_cached_cookie helpers return without raising in the same situation. Create the directory once, deliberately, then rerun.
Legacy pair .sig mismatchFor a --cache-file legacy pair the policy and its .sig are written together; a stale or mismatched .sig reads back as corrupt_cache and self-heals on the next successful remote fetch.
Stored record shows corrupt_cacheA container record that fails its magic, length, stream-boundary, or digest checks is treated as unusable and retried; it is rewritten from the next verified remote policy.
--show-state --output did not writeA monitoring agent holding the output path open can refuse both the atomic swap and the one in-place fallback; the state report still prints, a top-level detail names the reason, and the command exits 2.
--output did not writeThe report is written atomically through a staging file and os.replace, with one in-place fallback. When both fail the message names the path and the underlying error, for example Could not write JSON output to C:reportsout.json: FileNotFoundError: [Errno 2] No such file or directory, and the command exits 2 as before.
Cookie cache or cache.save_policy_cache file now ends lines with LFThe optional Windows Update cookie cache and the embedder-only cache.save_policy_cache / save_cached_policy helpers serialise their JSON and write the bytes through the atomic write primitive, so on Windows those two files contain LF instead of the previous CRLF. The JSON content is otherwise unchanged and every reader of them is unaffected. A --cache-file legacy pair is not one of them: it holds the publisher's exact policy and signature bytes and always did.

Home | Source Diagnostics | Agent Chokepoints