Docs

Troubleshooting

Symptom-first fixes for the failure modes that actually come up with this package — most of them are a security default or a config default working as intended, not a bug.

Absolute asset paths don't load in production (loadMode: 'file')

Symptom: images/scripts referenced with an absolute path (<img src="/logo.png">) work in dae run (dev server) but 404 or fail silently once packaged.

Cause: 'file' mode uses win.loadFile(), and file:// has no real origin, so an absolute path resolves against the filesystem root instead of dist/.

Fix: set base: './' in vite.config.ts so Vite emits relative asset paths — this is what the playground does. Don't switch app.loadMode to 'protocol' or 'server' just to work around this; those modes exist for other reasons (see App configuration).

window.open() / target="_blank" does nothing

This is intentional. The security defaults deny any window navigating away from its own origin or opening unrestricted new windows. Use window.Electron.windows.create() instead.

A permission request (camera, microphone, notifications, ...) is silently denied

Electron's own default is to allow every permission request; this package inverts that. Add the permission name to security.allowedPermissions in electron.config.ts (e.g. ['notifications']). See Configuration.

A window.Electron.* call returns { ok: false, error: { code: 'FORBIDDEN', ... } }

The IPC sender-trust check rejected the calling frame — it means the call came from a frame whose URL doesn't match what setIpcSenderCheck() was told to trust (dev server / file:// / custom protocol). This is the intended behavior for content the app doesn't fully control (e.g. an externally-navigated managed window); it should not happen from the app's own main window under normal operation. See Architecture.

autoLaunch returns UNSUPPORTED_OS

Launch-at-login is macOS/Windows only. On Linux, isEnabled()/setEnabled() resolve { ok: false, error: { code: 'UNSUPPORTED_OS' } } by design.

A fixed app.server.port fails to start

loadMode: 'server' fails startup with a clear error instead of silently picking a different port if the configured port is already in use — deliberate, since WebUSB/WebBluetooth/WebSerial device-permission grants are origin-scoped (port included), and silently changing port would invalidate previously-granted device permissions.

dev.url waits on the wrong port

If dev.url is a fixed URL but Vite's own dev server auto-incremented past its default port (because something else was already using it), dae run will wait on the wrong URL forever. Set dev.url: 'auto' instead — it inspects the project's vite.config for server.strictPort and either waits on the exact configured port or reads the real URL back out of Vite's own startup output. See CLI reference.

Leftover Electron/Node processes after a crashed dev session

Run npx dae kill to terminate any Electron/Node processes tied to the project left over from a previous dae run.

dae sync didn't pick up a newly installed plugin

dae sync only detects packages carrying a "dae": { "plugin": true } marker in their own package.json. Packages without the marker (or local plugin files) must be wired by hand into electron/plugins/user/{main,preload}.ts instead — see Plugins.

Known limitations (v1)

  • Vue/Svelte hook packages don't exist yet. The core window.Electron bridge is framework-agnostic, so it works in any framework in the meantime — only the @devioarts/electron/react convenience hooks are React-specific.

Last updated on July 17, 2026