HomeNewsletterCommunityMVP FeedToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog
Autopilot AutopilotIntuneRegistryTroubleshootingOOBE

Your Autopilot Profile Edit Didn't Apply: The Cache Nobody Checks

IA
Imran Awan
16 August 2026

You changed the Autopilot deployment profile in Intune. Maybe you flipped the user account type, or renamed it, or changed a group tag so a different profile should apply. You synced the device. Nothing changed. The device still behaves exactly like it did before, and the Intune portal cheerfully shows the new profile as assigned. Nothing is broken - you are looking at a cache, and the cache was written once, at provisioning time, and has not been touched since.

The short version

An Autopilot deployment profile is downloaded once, during provisioning, then cached in two places on the device: the registry value PolicyJsonCache under AutopilotPolicyCache, and a JSON file at C:\Windows\ServiceState\wmansvc\AutopilotDDSZTDFile.json. Editing the profile in Intune does not rewrite either copy on an already-provisioned device - the edit only takes effect at the next provisioning cycle. The cached JSON carries a PolicyDownloadDate, so you can prove exactly which version of the profile a device is holding. The same folder also caches the device's hardware hash and TPM endorsement key, which is worth knowing about for entirely separate reasons.

Note: This is not a bug and there is no setting to change. Autopilot is a provisioning technology - the profile describes how to build a device out of the box, not a policy that is continuously enforced afterwards. Once the device is built, the profile has done its job. Understanding that one sentence saves a lot of wasted troubleshooting.

The problem: the portal says one thing, the device does another

The symptom is always some version of "the profile does not match the device". Common shapes:

In every case the Intune portal is telling you the truth about assignment, and the device is telling you the truth about what it was built with. Those are two different facts, and they drift apart the moment you edit a profile.

Why it happens: the profile is cached, not polled

During OOBE, the device authenticates to the Autopilot deployment service, retrieves its assigned profile as a JSON document, and caches it locally so the rest of provisioning can read it without going back to the network. That cache is written twice:

  1. In the registry, as one long string in the PolicyJsonCache value under HKLM:\SOFTWARE\Microsoft\Provisioning\AutopilotPolicyCache. This is the copy most tooling reads.
  2. On disk, as C:\Windows\ServiceState\wmansvc\AutopilotDDSZTDFile.json. Same content, written by the Windows Management service.

Neither copy is refreshed on a schedule. There is no background task that re-reads your Intune profile and reconciles it. The cached JSON carries its own PolicyDownloadDate field recording when it was fetched, and on a device that has been in service for a while, that date can be very old indeed - which is exactly what makes it useful evidence.

Gotcha: the same folder also holds CachedHash.txt (the device's Autopilot hardware hash) and CachedTpmEkPub.txt (the TPM endorsement key public part). Both are strong device identifiers. Treat that folder as sensitive - do not copy its contents into a ticket, and be aware that anyone with administrative access to the device can read the hardware hash straight off disk without running any Microsoft tooling.

How to verify: read the cache and its download date

Two things worth pulling. First, the registry cache and its download date - this is the authoritative answer to "which profile version is this device holding?":

PowerShell — read the cached profile (run elevated)
# The whole assigned profile, as it was cached at provisioning time \$cache = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Provisioning\AutopilotPolicyCache' \$profile = \$cache.PolicyJsonCache | ConvertFrom-Json \$profile | Select-Object DeploymentProfileName, PolicyDownloadDate, CloudAssignedDomainJoinMethod, IsExplicitProfileAssignment

Second, the on-disk copy - and note the timestamps, because they should agree with the registry's PolicyDownloadDate:

PowerShell — the on-disk cache
Get-ChildItem 'C:\Windows\ServiceState\wmansvc' | Select-Object Name, Length, LastWriteTime # Do NOT cat CachedHash.txt or CachedTpmEkPub.txt - they are device identifiers. # Their existence and timestamp is all you need for troubleshooting.
Tip: compare PolicyDownloadDate against the date you edited the profile in Intune. If the download date is earlier, you have your answer in one line, and you can stop hunting. That single comparison resolves most "the profile is not applying" tickets.

The fix: make the edit actually land

Context: there is nothing to repair here, because nothing is broken. The fix is to trigger a new provisioning cycle so the device fetches the profile again, or to accept that the setting must be delivered by a mechanism that is continuously enforced.

Option 1 - re-provision the device so it downloads the current profile. From the Intune admin center:

  1. Sign in to intune.microsoft.com.
  2. Go to Devices › All devices and select the device.
  3. Choose Autopilot reset (keeps the device enrolled and re-runs provisioning) or Wipe (returns it to OOBE completely).
  4. On the next provisioning pass the device fetches the current profile and rewrites both caches.
intune.microsoft.comDevices › All devices[device]Autopilot reset

Option 2 - deliver the setting by policy instead. If what you actually need is an ongoing guarantee rather than a one-time build decision, the Autopilot profile is the wrong tool. For example, "the signed-in user must not be a local administrator" is enforced continuously by an Intune Settings Catalog policy or Group Policy targeting local group membership, not by the Autopilot profile's User account type field - which only decides what happens to the first user at first sign-in.

Watch out: do not try to "fix" this by hand-editing PolicyJsonCache or the JSON file. The cache is a record of what the deployment service sent, not a control surface. Editing it does not re-run any provisioning logic that already completed, it invalidates your ability to trust the device's own diagnostics, and it can leave the device reporting a profile it never actually applied. Re-provision instead.

Registry and file reference

Everything in this post lives under one registry parent and one folder:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\
Value or fileWhat it holdsWhy you care
AutopilotPolicyCache\PolicyJsonCache (REG_SZ)The entire assigned deployment profile as JSON, as fetched at provisioningThe authoritative record of what this device was actually built with, including PolicyDownloadDate
AutopilotPolicyCache\ProfileAvailable (REG_DWORD)1 when a profile was successfully retrieved and cached0 or absent on a device that never got a profile - a completely different failure to chase
Diagnostics\Autopilot\DeploymentProfileName (REG_SZ)Friendly name of the profile that built this deviceFast answer to "which profile did this come from?" without parsing JSON
Diagnostics\Autopilot\IsAutoPilotDisabled (REG_DWORD)0 on a normal Autopilot deviceNon-zero means Autopilot was explicitly disabled for this device
C:\Windows\ServiceState\wmansvc\AutopilotDDSZTDFile.jsonThe same profile JSON, on diskIts file timestamp corroborates the registry's PolicyDownloadDate
...\wmansvc\CachedHash.txtThe device's Autopilot hardware hashA device identifier readable by any local admin - treat as sensitive, do not paste into tickets
...\wmansvc\CachedTpmEkPub.txtTPM endorsement key public partAlso a device identifier - same handling rules

Proof it worked: a real device, two years of cache

Here is a genuine run of Get-AutopilotProfileCacheReport.ps1 from this series against a real Autopilot-provisioned, Entra hybrid joined device. Tenant identifiers and the internal profile name are replaced with placeholders; every date, flag and file size is exactly as captured:

PowerShell — Get-AutopilotProfileCacheReport.ps1 (real output, identifiers redacted)
Autopilot Profile Cache Report -------------------------------------------------------------- Deployment profile name : Corp Autopilot - Hybrid Join Autopilot disabled flag : 0 Forced enrollment : 1 OOBE config (bitmask) : 1308 Registry cache (HKLM:\SOFTWARE\Microsoft\Provisioning\AutopilotPolicyCache): ProfileAvailable : 1 PolicyDownloadDate : 2024-10-17T08:10:31Z <-- when the profile was cached AutopilotCreationDate : 2026-03-30T16:04:45Z DeploymentProfileName : Corp Autopilot - Hybrid Join DomainJoinMethod : 1 (Microsoft Entra hybrid join) ExplicitProfileAssign : True AutopilotUpdateDisabled: 1 On-disk cache (C:\Windows\ServiceState\wmansvc): AutopilotDDSZTDFile.json 1,800 bytes 10/17/2024 9:10:31 AM CachedHash.txt 8,002 bytes 10/17/2024 9:26:05 AM (hardware hash - contents deliberately NOT read) CachedTpmEkPub.txt 762 bytes 10/17/2024 9:26:05 AM (TPM endorsement key - contents deliberately NOT read)

Read what that actually tells you. The profile was downloaded on 17 October 2024. The on-disk JSON file's timestamp is 09:10:31 local, exactly matching the registry's 08:10:31Z UTC - a one-hour offset for British Summer Time, which is a satisfying confirmation that both caches were written by the same operation at the same instant. Anything the profile was changed to after October 2024 has never reached this device, and never will until it is re-provisioned. That is the entire explanation for the class of ticket this post is about, visible in one command.

Note also AutopilotCreationDate reading 2026-03-30, well after the download date. Those two fields answer different questions - one is when this device's Autopilot object was created or last updated service-side, the other is when this device last pulled its profile. Do not read them as a single timeline.

References

Microsoft MVP community deep-dives

Verified and genuinely on-topic - each URL was fetched and confirmed before being cited here, not copied on trust:

AuthorPostWhat it adds
Rudy Ooms (MVP, call4cloud.nl)Step by Step: How Windows Retrieves the Autopilot ProfileTraces the full eight-step token-and-profile retrieval flow, and independently documents both the AutopilotPolicyCache registry key and the wmansvc on-disk cache this post relies on
PowerShell Scripts — Autopilot Profile Cache

Script for this post is in Windows-Autopilot-Scripts.

Get-AutopilotProfileCacheReport.ps1 — read-only: reports the cached profile, its download date, and the on-disk cache files - deliberately never reads the hardware hash or TPM key contents
View all scripts on GitHub
Was this post helpful?
React below — no account needed
Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Autopilot
Reading AutopilotConfigurationFile.json: Every Documented Field…
Microsoft documents exactly nine properties for AutopilotConfigurationFile.json, and none…
Autopilot
CloudAssignedOobeConfig Decoded: Which OOBE Screens Your Profile…
One REG_DWORD on every Autopilot device encodes which OOBE screens your deployment…
Autopilot
The Autopilot Conditional Access deadlock: requiring a compliant…
A brand-new Autopilot device cannot be compliant before it is enrolled, so a Conditional…