0X0000047F

ERROR_APP_WRONG_OS (0x0000047F): Fix 'Not a Windows Program'

You're launching an executable built for a different OS or CPU architecture. Windows can't map it to a valid PE image, so it throws 0x47F before any code runs.

Quick answer: 0x0000047F means Windows read the executable's PE header and found a machine type or subsystem it can't run — wrong CPU architecture, a 16-bit or raw DOS binary, or a truncated download.

What's actually happening here is that CreateProcess never got as far as running your program. The loader parses the MZ stub at the top of the .exe, follows the offset to the PE signature, then checks the IMAGE_FILE_HEADER.Machine field against the architectures the current Windows install supports. If that machine value is IMAGE_FILE_MACHINE_I386 on an ARM64-only build, or IMAGE_FILE_MACHINE_ARM64 on a plain x64 Windows without emulation support, or IMAGE_FILE_MACHINE_UNKNOWN because the file is a DOS or OS/2 binary, the loader bails and returns STATUS_INVALID_IMAGE_WIN_32, which surfaces to Win32 as error 0x47F. The message "not a Windows or MS-DOS program" is slightly misleading — a real MS-DOS program triggers it too, because Windows 10 and 11 dropped NTVDM entirely. You'll hit this most often with old corporate installers pulled from a vendor FTP, a 16-bit helper .exe tucked inside a legacy app folder, or an ARM64 build of something you grabbed from a Windows on ARM machine and tried to run on your Intel desktop.

Step 1: Confirm what the binary actually targets

Don't guess. Read the header. Open an elevated PowerShell and run Get-Item against the file, then dump the machine type with a small script. If you have Visual Studio, dumpbin /headers program.exe prints the machine in the first block. Without VS, use this:

function Get-PEMachine($path) {
  $fs = [IO.File]::OpenRead($path)
  $br = New-Object IO.BinaryReader($fs)
  $fs.Seek(0x3C, 'Begin') | Out-Null
  $peOffset = $br.ReadInt32()
  $fs.Seek($peOffset, 'Begin') | Out-Null
  $sig = $br.ReadUInt32()
  if ($sig -ne 0x00004550) { 'Not a PE file'; $fs.Close(); return }
  $machine = $br.ReadUInt16()
  $fs.Close()
  switch ($machine) {
    0x014c { 'x86 (32-bit Intel)' }
    0x8664 { 'x64 (AMD64)' }
    0xAA64 { 'ARM64' }
    0x01c0 { 'ARM (32-bit)' }
    default { 'Unknown: 0x{0:X4}' -f $machine }
  }
}
Get-PEMachine 'C:\Path\To\program.exe'

If that returns "Not a PE file," you're dealing with an NE (16-bit Windows), LE, or straight MZ DOS binary. No amount of compatibility mode will fix it on modern Windows.

Step 2: Match the binary to the OS you're on

Check your architecture with $env:PROCESSOR_ARCHITECTURE. The rules are rigid:

  • x64 Windows runs x64 and x86 natively. It does not run ARM64.
  • ARM64 Windows runs ARM64, x86, and x64 (the last two via emulation), but only on Windows 11. Windows 10 on ARM doesn't do x64.
  • 32-bit Windows runs x86 only. An x64 binary hits 0x47F immediately.
  • No current Windows runs 16-bit NE or DOS MZ binaries. NTVDM was removed in Windows 8 for x86 and never existed for x64.

Step 3: Get the right build

If the file is x86 and you're on x64, it should have worked — so the header is probably corrupt. Re-download it. If the file is x64 and you're on a 32-bit install (rare now, but Surface Go 1 had a 32-bit firmware option), grab the x86 build from the vendor. If you've got an ARM64 binary on an Intel machine, download the x64 package instead.

Step 4: Rule out a broken download

Truncated downloads are the sneakiest cause of 0x47F because the MZ header looks fine and Explorer happily shows a file icon. Compare the SHA-256 against the vendor's published hash:

Get-FileHash .\program.exe -Algorithm SHA256

If it doesn't match, the loader is reading garbage where the PE signature should be. Re-download over a wired connection or a different network — I've seen captive-portal proxies silently truncate large .exe files at the 4 GB mark.

Alternative fixes when the above doesn't apply

You're stuck with a 16-bit or DOS binary

Use DOSBox-X for DOS programs or OTVDM (WineVDM) for 16-bit Windows apps. OTVDM is a clean reimplementation of the NTVDM user-mode pieces and runs most Win16 installers. Don't bother with Compatibility Mode's "Windows 95" setting — it changes reported version strings, not the loader's architecture check.

You need to run a program from a mounted ISO or network share

Some antivirus DLP agents mangle PE headers on the fly. Copy the .exe to a local NTFS folder and try again. If it works locally, the issue is the filter driver, not the binary.

Scripts disguised as executables

A file named install.exe that's actually a Python or AutoIt script packed by a lazy vendor can end up with a bogus machine field. Run Get-Content .\install.exe -TotalCount 2 — if you see #! or @echo off, it's a script with the wrong extension.

One more trap: Windows Sandbox and some Hyper-V containers report a different PROCESSOR_ARCHITECTURE than the host. If 0x47F appears only inside a sandbox, check the guest's architecture, not the host's.

Preventing this next time

Before downloading any executable, check the vendor's page for a platform selector — almost every installer now ships separate x86, x64, and ARM64 builds, and grabbing the wrong one is trivial. Keep a hash-check habit for anything over 50 MB. And if you maintain internal tools, stop shipping single-arch builds: use a .NET self-contained publish or wrap the binary in an MSI that fails with a helpful message instead of a raw loader error. Also note that 0x47F is often confused with 0xC1 (ERROR_BAD_EXE_FORMAT) and 0x7E (ERROR_MOD_NOT_FOUND) — those have different causes, and swapping one for the other sends you down the wrong diagnostic path.

Related Errors in Windows Errors
0X000020B6 AD Cross-Reference 0X000020B6: Fix Conflict 0XC000035A STATUS_INVALID_IMAGE_WIN_64 (0XC000035A) – 64-bit format mismatch 0X00001A3D Fix ERROR_ENLISTMENT_NOT_FOUND (0X00001A3D) on Windows Right Click Menu Missing Options in Windows 11 – Fix It

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.