HomeNewsletterCommunityToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog

Windows Autopilot Fails During OOBE: The Errors, Event IDs, and Fixes That Actually Matter

IA
Imran Awan
23 July 2026

It's a new hire's first day. IT handed over a laptop still in its box, the plan was "power it on, sign in, go" — that's the entire point of Autopilot. Instead the screen has been sitting on a spinning dial under "Just a moment" for eleven minutes, the new hire is refreshing their personal phone for something to do, and the helpdesk ticket that just landed on your desk says nothing more useful than "laptop broken." It isn't broken. Something specific failed during OOBE or the Enrollment Status Page, and there's almost always a real signature behind it — an Event ID, a HRESULT, or a documented error string. This post is a field guide to the ones that actually show up in real tenants, where they come from, and how to fix them without guessing.

This is not registration, deregistration, or hardware eligibility — that's covered elsewhere. This is what happens after a device is already registered and assigned a profile, and the deployment itself goes wrong during OOBE or ESP.

The problem

"Autopilot is broken" almost always means one of a small number of specific, observable states:

Each of these has a distinct cause. Treating "Autopilot is stuck" as one problem is exactly why the same ticket gets reopened three times before someone actually reads the event log.

📋 Note: Microsoft's own troubleshooting flow starts from the same place every time: confirm the device received a Windows Autopilot profile at all, then confirm the profile's settings are what you expect. Everything below sits underneath that one question.

Why it happens

Real Autopilot deployment failures fall into four buckets. Knowing which bucket you're in cuts most of the guesswork out of the fix.

1. Network / identity failures

The device can't reach the Windows Autopilot service, or it reaches it but the tenant match fails. Windows Autopilot downloads its profile as soon as a network connection is available, and again after every reboot — if that download never lands, nothing downstream can happen. The device's registry key HKLM\SOFTWARE\Microsoft\Provisioning\Diagnostics\Autopilot holds the evidence: a value called IsAutopilotDisabled set to 1 means the profile couldn't be downloaded — commonly a firewall, proxy, or captive-portal issue — and TenantMatched set to 0 means the signed-in user's Entra tenant doesn't match the tenant the device was registered against, which forces the user back to the start of OOBE. On the licensing side, users signing in without a valid Intune, EMS, or Microsoft 365 license will see Something went wrong — Can't connect to the URL of your organization's MDM terms of use. — a licensing error, not a network one, despite how it reads.

2. Profile-sync / assignment failures

The device is registered, but the specific profile assignment is broken or hasn't landed yet. This is the category that produces the Event Viewer entries ZtdDeviceIsNotRegistered (Event ID 807), ZtdDeviceHasNoAssignedProfile — Assigned profile does not exist (Event ID 809, meaning the profile that was assigned got deleted without being cleaned up first), and ZtdDeviceHasNoAssignedProfile — No profile assigned to the device, and no default profile found in the tenant (Event ID 815). It's also where you'll see SerialNumberMismatch / ProductKeyIdMismatch (Event ID 908) after a motherboard swap, and the Fix pending / Attention required status that appears after a hardware change, with the exact message: "We've detected a hardware change on this device. We're trying to automatically register the new hardware. You don't need to do anything now; the status will be updated at the next check in with the result."

⚠ Gotcha: re-enrolling a previously used self-deploying or pre-provisioned device throws error 0x80180014 if the old Intune device record wasn't deleted first — Microsoft changed self-deployment/pre-provisioning behaviour specifically so reused, reset, or redeployed devices need that record removed before they can enrol again. The same error code can also mean Windows MDM enrollment itself is set to Block in your enrollment restrictions — two unrelated causes, one error code.

3. App-timeout / ESP conflicts

The profile applied correctly and the device is trying to configure itself, but the Enrollment Status Page gets stuck waiting on an app install that will never finish. The single most common trigger: mixing line-of-business (LOB) apps and Win32 apps in the same ESP profile. Both install types run through TrustedInstaller, which refuses to run two installs at once — when that happens you get exactly this message on screen: Another installation is in progress, please try again later. A close cousin of this is the Microsoft 365 Click-to-Run install of Office, whose Teams Machine-Wide Installer component runs its own untracked MSI — ESP doesn't monitor that install, so it can silently collide with other Win32 MSI installs running at the same time and cause either one to fail. It's a timing issue, so it won't reproduce on every device.

4. Policy conflicts that block sign-in or force reboots mid-ESP

Certain device-targeted policies are actively incompatible with ESP and will either stall it or break sign-in entirely. Documented offenders include DeviceLock CSP settings like minimum password length or password complexity (breaks kiosk-style autologon during ESP), the AppLocker CSP (triggers an unexpected reboot when applied during ESP), the AutoAdminLogon registry value under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon being forced to 0, the PreferredAadTenantDomainName policy (breaks autologon when it populates DefaultUser0), and Security Baseline settings around UAC elevation prompts and virtualization-based security, which force extra reboots and extra credential prompts mid-ESP. Any of these can look identical to "the device is just stuck."

✅ Tip: if a device only ever hangs when a specific Configuration Profile or Security Baseline is assigned to it, and behaves normally without it, you're very likely in this fourth bucket — not a network or app problem at all.

How to verify

Don't fix blind. Confirm which bucket you're actually in first.

Event Viewer
Applications and Services Logs › Microsoft › Windows › ModernDeployment-Diagnostics-Provider › Autopilot
Event ID 809 Error ZtdDeviceHasNoAssignedProfile — Assigned profile does not exist

That's the exact path Microsoft's own troubleshooting guidance points to for reading Autopilot's OOBE-time log entries. Event IDs 100/101/103/109/111 are informational — normal profile retrieval. Event IDs 171/172 (with an HRESULT) point at a TPM attestation failure, relevant only to self-deploying mode. Event IDs 807/809/815/908 are the ones worth treating as real incidents.

Registry Editor
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\Diagnostics\Autopilot
IsAutopilotDisabled REG_DWORD 0x00000001
TenantMatched REG_DWORD 0x00000000
CloudAssignedTenantDomain REG_SZ contoso.onmicrosoft.com

If IsAutopilotDisabled is 1 or CloudAssignedTenantDomain is blank, the profile never downloaded — go check network/firewall requirements before touching anything else. If TenantMatched is 0, the person signing in used the wrong account or the device is registered to a different tenant than expected.

On Windows 11 user-driven deployments signed in with a Work or School account, there's also a built-in diagnostics page: enable Show app and profile configuration progress and Turn on log collection and diagnostics page for end users on the ESP profile, then on the device press Ctrl+Shift+D during OOBE or select View Diagnostics. It won't work with a personal Microsoft account, and it's Windows 11 + user-driven mode only.

PowerShell 7 — decode a suspect hardware hash
# If a CSV import silently does nothing, an unpadded Base64 hash is the usual cause. # Feed the suspect hash in — success just means it decodes without throwing. [System.Text.Encoding]::ascii.getstring( [System.Convert]::FromBase64String("DEVICE_HASH_HERE"))
⚠ Gotcha: that CSV-import failure throws HTTP 400 with the body Cannot convert the literal '[DEVICEHASH]' to the expected type 'Edm.Binary' — the device hash is captured as unpadded Base64 but Windows Autopilot expects it padded. If the decode above throws Invalid length for a Base-64 char array or string, add or trade "=" padding characters at the end (max two) until it decodes cleanly, then re-import.

The fix

Match the fix to the bucket you confirmed above.

Network / identity — confirm connectivity and licensing first

Re-check firewall/proxy access to the Windows Autopilot networking endpoints, confirm the signing-in user has a valid Intune/EMS/M365 license (this alone fixes the MDM-terms-of-use error), and if a fresh profile needs to be pulled mid-OOBE, force it with Shift+F10 to open a command prompt and run shutdown.exe /r /t 0 to restart immediately.

Profile-sync / assignment — the 0x80180014 unblock walkthrough

Intune Admin Center — unblock a device stuck on 0x80180014
  1. Sign in to the Microsoft Intune admin center.
  2. Select Devices in the left pane, then under By platform select Windows.
  3. Under Device onboarding, select Enrollment.
  4. Under Windows Autopilot, select Devices.
  5. Find the affected device and select its checkbox.
  6. In the toolbar, select Unblock device. No success message may appear — that's expected, not a failure.
  7. Redeploy the Windows Autopilot deployment profile to the device.

If that doesn't clear it, the second known cause is Windows MDM enrollment itself being blocked: go to Devices > Windows > Windows devices > Enrollment > Enrollment options > Device platform restriction, open the relevant restriction, and confirm Windows (MDM) is set to Allow, not Block.

For Event ID 809 (assigned profile no longer exists) or 815 (no profile assigned, no default profile), assign a valid Windows Autopilot deployment profile to the device and re-attempt enrolment. For the hardware-change "Fix pending" state, no manual action is needed unless it persists — if it does, deregister and re-register the device.

App-timeout / ESP conflicts — stop mixing install types in the same ESP window

Policy conflicts — target users instead of devices where you can

For UAC elevation and virtualization-based-security policies from the Security Baseline, target the policy to a user group instead of a device group so it applies after ESP rather than during it. For password/DeviceLock policies breaking autologon, set them to Not Configured during OOBE or move them to user scope. Confirm AutoAdminLogon hasn't been forced to 0 by an unrelated hardening script, and don't enable PreferredAadTenantDomainName on devices that also need OOBE autologon.

⚠ Warning: the Intune Connector for Active Directory (hybrid join scenarios) has its own separate failure mode: error 0x80070774 during ESP means there's a domain mismatch between where the connector is installed and where the device configuration is targeted. Fix by installing/configuring the connector in the matching domain — this is not fixable from the ESP profile itself.

Proof it worked

"It's gone from the error list" is not proof. Microsoft's own device-object behaviour after registration changes depends on prior MDM enrollment history, so the only reliable proof is reading the device's actual state back from Microsoft Graph — not assuming from a portal refresh. That's what the companion script Get-AutopilotDeploymentHealthCheck.ps1 does: for a given serial number, it reads the Windows Autopilot device identity object, the matching Intune managed device, and the Entra device object, and cross-references the profile assignment status, sync detail, and enrollment state against the failure signatures covered above — entirely read-only.

Download the script — GitHub

Get-AutopilotDeploymentHealthCheck.ps1 is free and open source. It's a genuinely read-only script — no writes to Autopilot, Intune, or Entra ID.

Get-AutopilotDeploymentHealthCheck.ps1 View full repo →
Example output below is illustrative, not a live-tenant capture. It matches the script's real structure and message wording, with fictional device values, so you can see what a run looks like before testing it yourself.
Get-AutopilotDeploymentHealthCheck.ps1 — example output (illustrative)
.\Get-AutopilotDeploymentHealthCheck.ps1 -SerialNumber "PF3ABC12" Connected to tenant: 11111111-2222-3333-4444-555555555555 as admin@contoso.onmicrosoft.com === Windows Autopilot device identity === SerialNumber : PF3ABC12 GroupTag : Finance-UK EnrollmentState : notContacted LastContactedDateTime: ManagedDeviceId : AzureAdDeviceId : ResourceName : FIN-LAPTOP-88 === Beta deployment profile assignment fields === AssignmentStatus : assignedUnkownSyncState AssignmentDetailedStatus : failed ProfileAssignedDateTime : 2026-07-20T11:04:52Z === Intune managed device === No matching Intune managed device found. Device has not completed MDM enrollment yet. === Microsoft Entra device object === No matching Entra device object found (or the device has never joined Entra ID). === Failure signature match === [FLAGGED] EnrollmentState is 'notContacted' with a profile AssignmentDetailedStatus of 'failed' - the profile never reached the device before it dropped to OOBE. === Summary === Serial number : PF3ABC12 Autopilot state : notContacted Profile status : assignedUnkownSyncState Intune enrolled : No Entra join type : unknown Signatures found: 1 This script performed read-only Graph queries only. No changes were made to any device, profile, or object.
📋 Note: the deployment-profile assignment status and sync-state fields used by this script only exist in the Microsoft Graph beta endpoint for windowsAutopilotDeviceIdentity, not v1.0. The script calls the beta endpoint explicitly and says so — treat any output from those specific fields as informational, not committed API surface, and re-verify if Microsoft changes it.

A clean result looks like: enrollmentState = enrolled, deploymentProfileAssignmentStatus = assignedInSync, and the Intune managed device's enrollmentProfileName matching the Windows Autopilot profile name you expected — not OfflineAutoPilotProfile-<guid>, which would mean the existing-devices JSON profile applied instead of your assigned online profile because the online one timed out.

References

Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Autopilot
Windows Autopilot: Complete Device Lifecycle Management Guide
The full deployment lifecycle from registration through retirement, with the deployment modes and ESP explained.
Intune
Deregister an Autopilot Device Out of Order and You Can Orphan It Permanently
The exact correct deregistration order across Intune, Autopilot, and Entra ID — and why skipping it causes unrecoverable device states.
Intune
Windows Hello for Business Provisioning Failures: The Real Fix
Another first-boot-day failure class — WHfB provisioning breaking silently right after a clean Autopilot deployment.