different-ai/openwork · error

Operating-system secure storage is unavailable for OpenWork-

Error message

Operating-system secure storage is unavailable for OpenWork-managed OAuth.

What it means

Thrown by `loadKey` when Electron's `safeStorage` is unavailable or reports that asynchronous OS-level encryption is not available. OpenWork-managed OAuth requires the operating system's credential store (Keychain, DPAPI, kwallet, etc.) to encrypt the vault key at rest; without it the module refuses to proceed rather than storing plaintext.

Source

Thrown at apps/desktop/electron/secure-vault-key.mjs:74

 *
 * @param {{
 *   filePath: string;
 *   loadSafeStorage: () => import("electron").SafeStorage;
 *   platform?: NodeJS.Platform;
 * }} options
 */
export function createDesktopVaultKeyProvider({
  filePath,
  loadSafeStorage,
  platform = process.platform,
}) {
  /** @type {Promise<Buffer> | null} */
  let pending = null;

  async function loadKey() {
    const safeStorage = loadSafeStorage();
    if (!safeStorage || !(await safeStorage.isAsyncEncryptionAvailable())) {
      throw new Error("Operating-system secure storage is unavailable for OpenWork-managed OAuth.");
    }
    if (platform === "linux" && safeStorage.getSelectedStorageBackend() === "basic_text") {
      throw new Error("A secure Linux password store is required for OpenWork-managed OAuth.");
    }

    /** @type {Buffer | undefined} */
    let encrypted;
    try {
      encrypted = await readFile(filePath);
    } catch (error) {
      if (error?.code !== "ENOENT") throw error;
    }

    if (encrypted) {
      /** @type {Awaited<ReturnType<typeof safeStorage.decryptStringAsync>> | undefined} */
      let decrypted;
      /** @type {Buffer | undefined} */
      let key;

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Run the app as a normal Electron main-process environment with an OS keyring available
  2. On Linux, install/enable a keyring service (gnome-keyring, KWallet) and ensure a desktop keyring session is active
  3. For CI/headless, use a virtual keyring (e.g. gnome-keyring with dbus) or document the limitation

Example fix

// before
// loadKey() throws: no safeStorage in bare Node script
// after
// only invoke the vault from Electron main after app is ready
app.whenReady().then(() => {
  const key = await getKeyProvider()(); // safeStorage available here
});
Defensive patterns

Strategy: try-catch

Validate before calling

async function secureStorageReady(safeStorage) {
  return Boolean(safeStorage) && (await safeStorage.isEncryptionAvailable?.());
}

Try / catch

try {
  const key = await getKey();
} catch (e) {
  if (e.message.startsWith('Operating-system secure storage is unavailable')) {
    showSetupGuide('Enable OS keyring / run inside Electron');
  } else throw e;
}

Prevention

When it happens

Trigger: Running outside a fully initialized Electron app (safeStorage module missing), a platform/browser build without OS credential-store integration, or `isAsyncEncryptionAvailable()` returning false due to a missing keyring service.

Common situations: Headless/CI Linux environments with no keyring daemon; Electron run in environments where the OS credential service is disabled; running the module in plain Node instead of Electron main process.

Related errors


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