different-ai/openwork · error

Electron desktop helper is unavailable: ${command}

Error message

Electron desktop helper is unavailable: ${command}

What it means

invokeElectronHelper is the typed wrapper around the Electron preload bridge `window.__OPENWORK_ELECTRON__.invokeDesktop`. When that bridge is not present on `window` — i.e. the code is not running inside the Electron renderer with the preload script loaded — there is no way to service the command, so the wrapper throws immediately with the requested command name to make the missing-runtime cause obvious. It is a deliberate fail-fast instead of silently returning undefined.

Source

Thrown at apps/app/src/app/lib/desktop.ts:233

        platform?: "darwin" | "linux" | "windows";
        version?: string;
        evalFatalBootstrapFailure?: string | null;
      };
    };
  }
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

async function invokeElectronHelper<C extends DesktopCommandName>(
  command: C,
  ...args: DesktopCommandArgs<C>
): Promise<DesktopCommandResult<C>> {
  const invokeDesktop = window.__OPENWORK_ELECTRON__?.invokeDesktop;
  if (!invokeDesktop) {
    throw new Error(`Electron desktop helper is unavailable: ${command}`);
  }
  return (await invokeDesktop(command, ...args)) as DesktopCommandResult<C>;
}

// Pure utility — resolves the selected workspace ID from a workspace list
// payload, handling legacy fields.
export function resolveWorkspaceListSelectedId(
  list: Pick<WorkspaceList, "selectedId" | "activeId"> | null | undefined,
): string {
  return list?.selectedId?.trim() || list?.activeId?.trim() || "";
}

// ---------------------------------------------------------------------------
// Desktop bridge (Electron IPC proxy)
// ---------------------------------------------------------------------------

// All bridge methods are implemented via invokeDesktop IPC. The Proxy
// automatically maps property access to `invokeDesktop(propertyName, ...args)`.

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Run the app in the Electron desktop build (or verify the Electron preload script is loaded) so window.__OPENWORK_ELECTRON__.invokeDesktop exists before invoking the command.
  2. Guard the call site with a capability check such as `if (!window.__OPENWORK_ELECTRON__?.invokeDesktop) return;` and show a web-appropriate UI instead of the desktop action.
  3. In tests/storybook, polyfill `window.__OPENWORK_ELECTRON__` with a stub invokeDesktop that returns canned DesktopCommandResult values.
  4. If you are in Electron but still see this, check preload path registration (webPreferences.preload) and console errors from the preload script.

Example fix

// before
const icon = await getDesktopFileIcon(path);

// after
if (!window.__OPENWORK_ELECTRON__?.invokeDesktop) {
  console.warn("Desktop helper unavailable; skipping file icon.");
  return null;
}
const icon = await getDesktopFileIcon(path);
Defensive patterns

Strategy: try-catch

Validate before calling

const canUseDesktop = typeof window !== "undefined" && typeof window.__OPENWORK_ELECTRON__?.invokeDesktop === "function";

Type guard

function hasElectronBridge(w: unknown): w is { __OPENWORK_ELECTRON__: { invokeDesktop: (...args: unknown[]) => Promise<unknown> } } {
  return typeof window === "object" &&
    typeof (window as { __OPENWORK_ELECTRON__?: unknown }).__OPENWORK_ELECTRON__ === "object" &&
    typeof (window as { __OPENWORK_ELECTRON__?: { invokeDesktop?: unknown } }).__OPENWORK_ELECTRON__?.invokeDesktop === "function";
}

Try / catch

try {
  return await invokeElectronHelper("getDesktopFileIcon", path);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("Electron desktop helper is unavailable")) {
    return null; // web build: no desktop icons
  }
  throw err;
}

Prevention

When it happens

Trigger: Any typed desktop command routed through invokeElectronHelper — cancel, desktopUploadMultipart, desktopDownloadBinary, result, getDesktopFileIcon, getDesktopApplicationsForFile — executed while `window.__OPENWORK_ELECTRON__` or its `invokeDesktop` method is undefined, such as in a plain browser build, during SSR/SSR hydration, before the Electron preload has attached the bridge, or in an old desktop build lacking the API.

Common situations: Running the web (non-Electron) build of the app and clicking a desktop-only action like 'Reveal in Finder' or a file download that uses the desktop multipart upload; an Electron app updated to a renderer whose preload script failed to load (e.g. contextIsolation/sandbox changes) so the bridge never registers; unit or Storybook tests that import desktop.ts and render components without mocking the window bridge.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/cc88dda65041d811. Report an issue: GitHub.