What's New in v27
electron-builder v27 is a major release: it moves the entire ecosystem to native ES modules, raises the minimum runtime to Node.js 22.12.0, adds several new capabilities, and quietly changes a handful of defaults. This page is the front door — a short tour of what's new, plus the silent behavior changes most likely to trip you up.
Run electron-builder migrate-schema to auto-apply the config-key changes; the table below is what it does not do for you. For the ordered upgrade steps, follow the v26 → v27 walkthrough; for the full catalogue of everything that changed, see v27 Breaking Changes.
New in v27
- MSIX target (beta) — a
win.target: "msix"alongside AppX, producing.msix/.msixbundle/.msixuploadartifacts with modern manifest features (Package Integrity, Windows Services). Purely additive; the defaultwinCodeSigntoolset is MSIX-capable. - Cloudflare R2 publish provider — an opt-in, S3-compatible
provider: "r2"target with matching electron-updater support. Credentials come fromCF_R2_ACCESS_KEY_ID/CF_R2_SECRET_ACCESS_KEY. - Windows PKCS#11 & HSM code signing — two new
win.signmodes (beta):pkcs11(cross-platform viaosslsigncode— sign Windows apps from macOS/Linux CI with no Windows VM) andhsm(Windows CSP / FIPS token). - DMG
ULMO/ LZMA format — a newdmg.format: "ULMO"for LZMA-compressed images (macOS 10.15+), typically ~30% smaller than the defaultUDZO. Additive; the default format is unchanged. - Signed update manifests —
latest*.ymlis Ed25519-signed at publish time and verified by electron-updater before any download, against a trust list embedded in the app. Supports multi-key dual-signing for key rotation. Required by default — see the table below. - electron-updater
allowUnverifiedLinuxPackages— a newAppUpdaterflag to enforce GPG signature checks when installing.deb/.rpmauto-updates. Additive; defaults totrue(historical behavior). - Flatpak builds in unprivileged containers — the new
flatpak.additionalArgsoption passes arguments toflatpak-builder,flatpak build-exportandflatpak build-bundle(itsflatpakBuilder,buildExportandbuildBundlelists); with--disable-rofiles-fuseand--disable-sandboxthe flatpak target builds in CI containers that have neither FUSE nor user namespaces.flatpak.installOrUpdateRefsbuilds with the runtime, SDK and base app that are installed, without installing or updating them, for images that have them and for offline builds. The options are additive, but the target now requires newer tools and defaults to a newer runtime — see the table below. fileOptions—files,extraResourcesandextraFilesare grouped under onefileOptionsobject, at the root and per platform (mac.fileOptions), the same waydirectoriesgroups the build directories;migrate-schemamoves them for you.migrate-schemaCLI — a new command that rewrites your v26 config to v27 form in place, covering both static (json/json5/yaml/package.json) and programmatic (.js/.ts/.cjs/.mjs) configs.- Native ESM + Node.js >=22.12 — every package now ships as native ES modules. On Node.js 22.12.0+ both
importand CJSrequire()continue to work with no code changes.
New defaults and behavior changes you may trip over
These are the runtime and default changes that migrate-schema does not rewrite for you — no config key changed, so the migrator can't see them. Skim the list; each row deep-links to the full explanation.
| Change | One-line impact | Details |
|---|---|---|
| Node.js >=22.12.0 required | The build fails on older Node — bump your local runtime, CI, and Docker images. | → |
Toolsets resolve to "latest" | Unset / "latest" now fetch the newest bundle (winCodeSign 1.3.0, FUSE3 AppImage, NSIS 3.12); pin "0.0.0" to restore a legacy bundle. | → |
| Wine is the host install | toolsets.wine defaults to "system": building Windows targets on macOS now needs Wine installed (brew install --cask wine-stable). | → |
| macOS default entitlements tightened | The bundled default grants only allow-jit; apps loading native modules or frameworks signed by another Team ID (or unsigned) must add disable-library-validation back in build/entitlements.mac.plist. | → |
| Missing production dependencies fail the build | An unresolvable production dependency is now an error instead of a warning; allowMissingDependencies: true restores warn-only. | → |
| Native binaries verified against the target | A .node addon built for another platform/arch (e.g. a stale host binary) now fails the build; nativeModules.verifyNativeBinaries: "warn" restores warn-only. | → |
extraFiles / extraResources to validated | An absolute to, or one escaping the output dir, now throws. | → |
Windows publisherName validated | A win.sign.publisherName that does not match the signing certificate now fails the build, and so does a signed build that writes app-update.yml without a derivable publisher name (a custom win.sign.sign hook without publisherName, even with a certificate configured, or a certificate without a CN) — set win.sign.publisherName. | → |
| Signed update manifests required | A publishing build with a target that writes latest*.yml (NSIS, AppImage, deb/rpm/pacman, macOS zip/dmg) now fails at build start without an Ed25519 key (electron-builder create-update-key + ELECTRON_BUILDER_UPDATE_SIGN_KEY); updateManifest: false opts out with a warning. Non-publishing builds only warn. | → |
| Suffixed update channels expand | With generateUpdatesFilesForAllChannels, a channel such as beta-arm64 now also writes alpha-arm64.yml. | → |
node_modules arch/os-filtered every build | Dependencies whose cpu / os mismatch the target are now excluded from the app (was effectively universal-macOS only). | → |
arch: "all" -> x64 + arm64 | "all" no longer includes ia32 — request ia32 explicitly. Windows ia32 / Linux armv7l fail fast on Electron 44+. | → |
electron / electron-builder excluded from node_modules | Listing them in dependencies no longer errors — they're dropped from the copied node_modules; tune the set via ignoredProductionDependencies. | → |
DMG filesystem defaults to APFS | New images use APFS (was HFS+); set dmg.filesystem: "HFS+" only for pre-10.13 macOS compatibility. | → |
disableWebInstaller defaults to true | electron-updater rejects NSIS web-installer updates (ERR_UPDATER_WEB_INSTALLER_DISABLED) unless disableWebInstaller is false; installs made by a v27+ nsis-web installer opt in automatically. | → |
nsis-web installer verifies its app package | A --package-file package or a publish-URL download that doesn't match the packages built with the installer aborts the install (exit code 2); the installer verifies and installs its own copy of a local package and leaves the local file in place. nsisWeb.allowUnverifiedAppPackage opts out. | → |
NSIS per-machine builds set isAdminRightsRequired | Updates of per-machine nsis / nsis-web builds are started with elevate.exe, and "onNextLaunch" doesn't auto-install them — call installPendingUpdateIfAvailable(). | → |
| Update credentials stay on the feed's origin | requestHeaders / addAuthHeader credentials and the feed URL's query are not sent to downloads on another origin; serve update files from the feed origin or use pre-signed URLs. A custom provider used with credential headers must override Provider.feedBaseUrl. | → |
latest*.yml drops top-level path/sha512 | Update metadata now carries only files[]; read info.files[0] and set electronUpdaterCompatibility if you still ship pre-2.16 updaters. | → |
| Bitbucket token without username -> Bearer auth | A BITBUCKET_TOKEN with no username is now sent as Bearer; set BITBUCKET_USERNAME if it's an app password / API token needing Basic auth. | → |
macOS productName / executableName validated | A name that would need filename sanitization now throws at build start instead of being silently rewritten. | → |
| NSIS file-association ProgID format changed | Associations now register under a unique generated ProgID; update custom NSIS scripts that hard-code the old name/extension. | → |
Linux .desktop runs a *-launcher script | Every Linux target except flatpak launches via a generated <executableName>-launcher; the .desktop Exec points at it. Update custom .desktop / AppArmor / MIME tooling. | → |
AppImage --no-sandbox only for legacy FUSE2 | With the default FUSE3 runtime, --no-sandbox is no longer auto-added; set appImage.executableArgs: ["--no-sandbox"] if you need it unconditionally. | → |
Flatpak needs flatpak 1.12.4+ and flatpak-builder 1.2.2+ | Older tools fail the build. The stock packages of Ubuntu 22.04, Debian 12, RHEL 8 and 9 and newer releases are new enough. The electronuserland/builder images with a date tag newer than -05.26 include the tools, those up to -05.26 none. DEBUG=@malept/flatpak-bundler is replaced by DEBUG=electron-builder. | → |
Flatpak defaults to the 26.08 runtime | flatpak.runtimeVersion / baseVersion default to 26.08 (was 20.08, which is end-of-life): a build that sets neither is built for that runtime, and the build machine installs its runtime, SDK and base app if they are missing (about 3.2 GB). Set both to "20.08" to keep the previous runtime. | → |
Flatpak files and symlinks stay inside the app | A flatpak.files destination or flatpak.symlinks link that leaves the app prefix with .., or a directory in flatpak.files copied onto a symlink to a directory, now fails the build. | → |
| Flatpak: no home directory access by default | Without flatpak.finishArgs, the app gets the Downloads folder (--filesystem=xdg-download) instead of the whole home directory. Its data under ~/.var/app and the files the user picks in a dialog are unaffected; other paths, such as recent files, ~/Documents, dotfiles and the certificates in ~/.pki/nssdb, are no longer reachable. Set finishArgs to the v26 list or add narrower grants. | → |
| Flatpak: no notifications talk-name on current base apps | Without flatpak.finishArgs, and unless the base is org.electronjs.Electron2.BaseApp before 23.08 (the default is 26.08; any other base gets no talk-name either), --talk-name=org.freedesktop.Notifications is left out and notifications go through the notification portal. On desktops without a portal backend for notifications, such as sway with only xdg-desktop-portal-wlr, they no longer appear: add the talk-name to finishArgs. | → |
Snap core24 drops allow-sandbox by default | Default core24 snaps request plain browser-support (the Snap Store rejects allow-sandbox from non-vetted publishers), launch with --no-sandbox, and omit chrome-sandbox. "default" in core24.plugs now merges your entries into the full default set. | → |
Azure Trusted Signing uses signtool /dlib | The default winCodeSign 1.3.0 ships the ATS dlib payload, so ATS uses the faster path automatically; pin below 1.3.0 to force the legacy PowerShell path. | → |
Consolidated custom NSIS artifacts to toolsets.nsis | Artifacts provided by .customNsisBinary, .customNsisResources config are now provided by on bundle set via toolsets.nsis. This is breaking change if you used those configs with manual migration steps required. | → |
This is the short list of high-traffic surprises. For the complete, authoritative catalogue — including config-key renames the migrator does handle — see v27 Breaking Changes.