electron-ipc-module
    Preparing search index...

    Diagnostics reference

    Every message this package produces, what causes it, and what to change. Search for the literal text you saw. For failure behavior — which stage swallows an error and which propagates it — see the error contract; for symptom-first debugging of a build that produces no message at all, see build and preload troubleshooting.

    These throw and write no output. The CLI reports them and exits non-zero; the Rollup plugin fails the build. Nothing is partially generated, so the committed bridge stays as it was.

    Prefixed with file:line:column. The bridge groups channels under one entry named after the file, so a second module in the same file would never reach the renderer while still registering successfully in main — the two sides would disagree silently. Move the second module into its own *.ipc.ts file.

    The prefix was a variable, constant, or template expression. The generator reads it statically to compute physical channel names, and cannot evaluate your code. Inline the literal:

    // Not analyzable
    defineIpcModule(PREFIX, channels);

    // Analyzable
    defineIpcModule("profile", channels);

    A channel key, event name, module file name, or expose value did not convert into a valid JavaScript identifier. Keys are camel-cased and event names pascal-cased, so a name beginning with a digit, or containing punctuation other than -, _, or a space, survives the conversion unusable: 2fa stays 2fa, which cannot be a property in the generated object literal. The message prefix names the source — expose option, channel "…", event "…" on-listener, or module file "….ipc.ts". Rename it.

    Two names converted to the same identifier. Within IPC module "<name>" that means two channel keys, or a channel and an event listener, collapsed together: get-all and getAll both produce getAll. Within IPC bridge it means two module files did, such as my-module.ipc.ts and myModule.ipc.ts. The message names both sources. Rename one.

    The requested key already exists on window or globalThis — name, location, top, self, constructor, and so on. Electron cannot overwrite it and TypeScript cannot safely redeclare it, so the exposure would type-check and then leave window.<key> untouched at runtime. Pick a key of your own, such as ipc.

    Followed by formatted compiler diagnostics. This covers a missing or malformed tsconfig (TS5083: Cannot read file …), invalid compiler options, and syntax or type errors. Type errors are scoped to the IPC sources and the files they import, so an unrelated broken file elsewhere in the project cannot fail generation. If the diagnostics look like the whole project, check that tsconfig points at the config you meant — a solution file with "files": [] produces zero modules rather than an error, which is the quieter version of the same mistake.

    The generator probes the standard library to learn which global keys expose must avoid, and the probe came back empty. The resolved lib files are missing or unreadable — check lib, types, and typeRoots in the tsconfig you passed, and that typescript is installed where the generator runs.

    Logged as [<module>] <message>. Part of the bridge could not be typed completely, and --quiet does not suppress these.

    The channels object used a spread. Those channels register at runtime but the analyzer cannot enumerate them, so the renderer gets no wrapper and the two sides disagree. List the channels explicitly.

    eventPrefix was a computed value. The runtime still applies it, but the generator cannot know the physical event channel, so the generated listeners subscribe to the wrong name. Use true or an inline string.

    The channel's arguments, return value, or — for a stream — yielded chunk cannot cross the IPC boundary — typically a function, Promise, symbol, or a class instance carrying methods, anywhere inside the payload. Structured clone rejects the whole payload rather than dropping the offending member, so the check fires at the declaration instead of producing a half-mapped renderer type. Return plain data, or map to a DTO inside the handler. The full table of what survives is in the README.

    The validate map is keyed against the declared channels, so a misspelled entry is a compile error rather than a guard that silently never runs. Check the key against the channels object.

    Error code Raised when
    IpcAuthorizationError — authorize returned exactly false. A thrown authorization error is preserved instead of being replaced.
    IpcValidationError — A Standard Schema rejected the payload. Carries the schema's issues in the order it reported them.
    IpcChannelCollisionError IPC_CHANNEL_COLLISION Two loaded modules claim the same physical channel, or one module declares it twice. The incoming registration is cleaned up.
    IpcContainerDisposedError IPC_CONTAINER_DISPOSED A lifecycle call was made after dispose(). Terminal; reads still work.
    IpcObserverError IPC_OBSERVER_ERROR A loaded or unloaded observer threw. Reported on error, and the completed work is not undone.
    AggregateError — Registration rollback, unload, or dispose hit more than one failure. Inspect .errors.

    Plus these messages:

    • IPC module "…" is already loaded — loadAll is insert-only. Use load() to replace one module deliberately.
    • loadAll cannot replace already-loaded modules (…) — the same cause, raised before any registration starts so the batch stays transactional.
    • event.signal requires a global AbortController, which Electron ships from 15.0.0 — a handler read event.signal on an older runtime. The signal is built on first read, so handlers that never touch it keep working on the package's Electron 12 peer floor.
    • IPC stream "…" needs a unique string call id — the start channel of a stream was invoked without the per-call id the generated bridge supplies, or with one already in flight. A renderer calling ipcRenderer.invoke on the channel by hand, rather than through the bridge, is the usual cause.
    • [electron-ipc-module] Stream cleanup failed for "…" — a stream was cancelled or its sender destroyed, and the generator's finally threw while return() ran it. The renderer has stopped listening, so it is logged. Keep cleanup in finally from throwing.
    • Error invoking remote method '…': … in the renderer, from a stream — the stream callback threw, before its first yield or mid-stream; the text after the colon is the error's string form. See the error contract.
    • [electron-ipc-module] Unhandled error in listener "…" — a listen channel rejected and no onListenerError was configured. Fire-and-forget channels have no response path, so the failure is logged rather than returned to the renderer. Configure the hook to route it into application logging.
    • [electron-ipc-module] onListenerError failed for "…" — the hook itself threw. Keep it trivial; a hook that can fail loses both its own error and the original.
    • Generated bridge is stale: <path> — check found output that differs from what generation would write. Regenerate and commit the result. Options that differ between generate and check produce this even when nothing changed, so keep both in package scripts.
    • Unknown command … / Unknown option … / … requires a value — see electron-ipc-module --help.
    • check does not support --watch — check is a single verification pass. Use generate --watch for a watch loop.