oven-sh/bun · error · bun_exe_format::pe::Error
UnsupportedPEFormat
Error message
UnsupportedPEFormat
What it means
The optional header magic is not 0x020B (PE32+/64-bit), so Bun refuses the image (src/exe_format/pe.rs:291-293). Bun's .bun-section injector only understands 64-bit PE images because the injected section layout (OptionalHeader64, 16 data directories) assumes PE32+. A 32-bit PE has magic 0x010B and a different optional-header shape, so parsing on would be unsound.
Source
Thrown at src/exe_format/pe.rs:23
use core::ptr;
use core::slice;
// New error types for PE manipulation
#[derive(thiserror::Error, strum::IntoStaticStr, Debug, Copy, Clone, Eq, PartialEq)]
pub enum Error {
#[error("OutOfBounds")]
OutOfBounds,
#[error("BadAlignment")]
BadAlignment,
#[error("Overflow")]
Overflow,
#[error("InvalidPEFile")]
InvalidPEFile,
#[error("InvalidDOSSignature")]
InvalidDOSSignature,
#[error("InvalidPESignature")]
InvalidPESignature,
#[error("UnsupportedPEFormat")]
UnsupportedPEFormat,
#[error("InsufficientHeaderSpace")]
InsufficientHeaderSpace,
#[error("TooManySections")]
TooManySections,
#[error("SectionExists")]
SectionExists,
#[error("InputIsSigned")]
InputIsSigned,
#[error("InvalidSecurityDirectory")]
InvalidSecurityDirectory,
#[error("SecurityDirInsideImage")]
SecurityDirInsideImage,
#[error("UnexpectedOverlayPresent")]
UnexpectedOverlayPresent,
#[error("InsufficientSpace")]
InsufficientSpace,
}View on GitHub (pinned to 8c5296ac45)
Solutions
- Use the 64-bit Bun executable as the base (bun-windows-x64 / bun-windows-aarch64); Bun ships only PE32+ binaries.
- Verify the base with `file base.exe` — it must report 'PE32+ executable', not 'PE32 executable'.
- Clear stale build caches (BUN_COMPILE_CACHE) that may hold a 32-bit base from earlier experiments.
- If you must target 32-bit Windows, that is unsupported by `bun build --compile`; ship the 64-bit binary instead.
Example fix
# before file base.exe # 'PE32 executable (console) Intel 80386' bun build app.ts --compile --target=windows-x64 --base base.exe # after: fetch the matching 64-bit base file bun.exe # 'PE32+ executable (console) x86-64' bun build app.ts --compile --target=windows-x64
Defensive patterns
Strategy: validation
Validate before calling
const bytes = await Bun.file('base.exe').arrayBuffer();
const dv = new DataView(bytes);
const peOff = dv.getUint32(0x3c, true);
const optMagicOff = peOff + 4 + 20; // signature + COFF header
if (dv.byteLength < optMagicOff + 2 || dv.getUint16(optMagicOff, true) !== 0x020b) {
throw new Error('base.exe is not PE32+ (64-bit) — get the x64/arm64 Bun build');
} Prevention
- Run `file base.exe` and require 'PE32+' in CI before compile steps
- Only download bases from official Bun release artifacts for the exact target arch
- Automate base selection from --target so humans never hand-pick mismatched exes
When it happens
Trigger: `bun build --compile` targeting Windows with a 32-bit (i386) base executable, e.g. a manually supplied 32-bit bun build, an old 32-bit launcher used as the base, or any PE32 image. Thrown when optional_header.magic != 0x020B in PEFile::init.
Common situations: Mixing architectures: building with a windows-x64 target while the base exe on PATH or in the cache is 32-bit; legacy toolchains producing PE32 wrappers; using a 32-bit stub loader as the custom base for Bun compilation.
Related errors
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/b9c28671eba21db4.
Report an issue: GitHub.