QL-Win/QuickLook · error · PEImageParseException
DOS header not found.
Error message
DOS header not found.
What it means
Thrown after reading the first UInt16 when it is not 0x5a4d (little-endian 'MZ'). Every DOS/PE executable begins with the 'MZ' mark, so a mismatch means the file is not a Microsoft executable despite being at least 2 bytes. PEImageParseException(0, ...) records the error at offset 0.
Source
Thrown at QuickLook.Plugin/QuickLook.Plugin.PEViewer/PEImageParser/PEImage.cs:52
/// <summary>
/// Gets the optional header of this PE image file.
/// </summary>
public ImageOptionalHeader OptionalHeader { get; private set; }
/// <summary>
/// Gets the collection of section headers and data of this PE image file.
/// </summary>
public ImageSection[] Sections { get; private set; }
private PEImage(byte[] originalImage)
{
OriginalImage = originalImage;
using BinaryReader reader = new(new MemoryStream(OriginalImage));
// MZ
if (reader.BaseStream.Length < 2) throw new PEImageParseException(0, "DOS signature not found.");
if (reader.ReadUInt16() != 0x5a4d) throw new PEImageParseException(0, "DOS header not found.");
// DOS Header
if (reader.BaseStream.Length - reader.BaseStream.Position < 64) throw new PEImageParseException((int)reader.BaseStream.Position, "DOS header incomplete.");
DosHeader = new()
{
LastPageSize = reader.ReadUInt16(),
PageCount = reader.ReadUInt16(),
RelocationCount = reader.ReadUInt16(),
HeaderSize = reader.ReadUInt16(),
MinAlloc = reader.ReadUInt16(),
MaxAlloc = reader.ReadUInt16(),
InitialSS = reader.ReadUInt16(),
InitialSP = reader.ReadUInt16(),
Checksum = reader.ReadUInt16(),
InitialIP = reader.ReadUInt16(),
InitialCS = reader.ReadUInt16(),
RelocationOffset = reader.ReadUInt16(),View on GitHub (pinned to cb5d9c429c)
Solutions
- Sniff the first 2 bytes for 'MZ' (0x5A4D) before constructing PEImage.
- Use TryCanHandle-style detection so non-PE files never reach the parser.
- Catch PEImageParseException and show 'not a valid PE/EXE' instead of crashing.
- Route ELF/Mach-O files to the correct viewer.
Example fix
// before if (reader.ReadUInt16() != 0x5a4d) throw new PEImageParseException(0, "DOS header not found."); // after — caller-side magic check using var fs = File.OpenRead(path); var b0 = fs.ReadByte(); var b1 = fs.ReadByte(); if (b0 != 0x4D || b1 != 0x5A) return null; // not 'MZ'
Defensive patterns
Strategy: validation
Validate before calling
using var fs = File.OpenRead(path); int b0 = fs.ReadByte(), b1 = fs.ReadByte(); if (b0 != 0x4D || b1 != 0x5A) return; // not 'MZ'
Type guard
static bool HasMzMagic(byte[] head) => head.Length >= 2 && head[0]==0x4D && head[1]==0x5A;
Try / catch
try { var img = PEImage.FromFile(path); }
catch (PEImageParseException ex) when (ex.Message.Contains("DOS header not found")) { /* not an executable */ } Prevention
- Sniff the 'MZ' magic before PE parsing.
- Route ELF/Mach-O and non-PE files elsewhere.
- Use TryCanHandle-style detection so mismatches never reach the parser.
When it happens
Trigger: Constructing PEImage from a byte array whose first two bytes are not 0x4D 0x5A — e.g. an ELF Mach-O, a text/script file, a .NET assembly's raw IL dump, or arbitrary data misnamed .exe.
Common situations: Previewing a non-PE file whose extension routed it to PEViewer; an installer stub that is actually an SFX container with a non-standard preamble; cross-platform binaries (ELF/Mach-O) opened on Windows.
Related errors
- DOS signature not found.
- DOS header incomplete.
- Section '{Header.Name}' incomplete.
- The file does not have a minidump signature.
- Offset is before the current position in the stream.
AI-assisted analysis of QL-Win/QuickLook@cb5d9c429c (2026-08-13).
Data as JSON: /api/errors/2650b31f8dd77857.
Report an issue: GitHub.