different-ai/openwork · error

${result}

Error message

${result}

What it means

openDesktopPath forwards the `__openPath` command to the Electron bridge, which returns a string error description on failure (empty string on success). Any non-empty result is thrown as-is, so the message text comes from the main process — typically the OS failing to open the file/folder with its default handler.

Source

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

export async function openDesktopUrl(url: string): Promise<void> {
  const safeUrl = assertDesktopWebUrl(url);
  const openExternal = window.__OPENWORK_ELECTRON__?.shell?.openExternal;
  if (openExternal) {
    const result = await openExternal(safeUrl);
    if (result && result.ok === false) {
      throw new Error(result.error ?? "Failed to open browser");
    }
    return;
  }
  if (typeof window !== "undefined") {
    window.open(safeUrl, "_blank", "noopener,noreferrer");
  }
}

export async function openDesktopPath(target: string): Promise<void> {
  const result = await invokeElectronHelper("__openPath", target);
  if (typeof result === "string" && result.trim()) {
    throw new Error(result);
  }
}

export async function revealDesktopItemInDir(target: string): Promise<void> {
  const result = await invokeElectronHelper("__revealItemInDir", target);
  if (typeof result === "string" && result.trim()) {
    throw new Error(result);
  }
}

export async function getDesktopFileIcon(target: string, size?: "small" | "normal" | "large"): Promise<string | null> {
  return invokeElectronHelper("__getFileIcon", target, size);
}

export async function applyBrandAppName(appName: string | null): Promise<string> {
  const result = await invokeElectronHelper("__applyBrandAppName", appName);
  return result.appName;
}

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Verify the target path exists and is accessible (`await fs.access(path)` / ls the path) before calling openDesktopPath; refresh the file listing if it is stale.
  2. Associate a default application for the file type in the OS, or use openDesktopWithApp to pick an explicit app.
  3. If the intent is just to show the file's folder, call revealDesktopItemInDir instead, which only needs the parent directory.
  4. Read the thrown message (from the main process) for the exact OS reason — ENOENT vs no handler vs EACCES — and fix accordingly.

Example fix

// before
await openDesktopPath(projectConfigPath);

// after
if (!(await exists(projectConfigPath))) {
  showToast("File no longer exists");
  return;
}
await openDesktopPath(projectConfigPath);
Defensive patterns

Strategy: validation

Validate before calling

async function pathExists(p: string): Promise<boolean> {
  try { await fs.promises.access(p); return true; } catch { return false; }
}
// call: if (!(await pathExists(target))) return showToast("File not found");

Try / catch

try {
  await openDesktopPath(target);
} catch (err) {
  showToast(`Could not open item: ${err instanceof Error ? err.message : err}`);
}

Prevention

When it happens

Trigger: invokeElectronHelper("__openPath", target) returning a non-empty string, i.e. the main process could not open `target` — path does not exist, no default application for the file type, or permission denied.

Common situations: Opening a config/workspace file that was deleted or moved after the UI listed it; a file type with no associated app on the machine (e.g. a dotfile on a fresh Linux install); a path on an unmounted drive or network share; a project dir opened via a stale symlink.

Related errors


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