{"record":{"id":"bfbfea48d794d6cb","repo":"usebruno/bruno","slug":"safestorage-decryption-failed-err-message","errorCode":null,"errorMessage":"SafeStorage decryption failed: ${err.message}","messagePattern":"SafeStorage decryption failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-electron/src/utils/encryption.js","lineNumber":93,"sourceCode":"  const encryptedString = encryptedStringBuffer.toString('hex');\n\n  return encryptedString;\n}\nfunction safeStorageDecrypt(str) {\n  try {\n    // Convert the hexadecimal string to a buffer\n    const encryptedStringBuffer = Buffer.from(str, 'hex');\n\n    // Decrypt the buffer\n    const decryptedStringBuffer = safeStorage.decryptString(encryptedStringBuffer);\n\n    // Convert the decrypted buffer to a string\n    const decryptedString = decryptedStringBuffer.toString();\n\n    return decryptedString;\n  } catch (err) {\n    console.error('SafeStorage decryption failed:', err);\n    throw new Error('SafeStorage decryption failed: ' + err.message);\n  }\n}\n\nfunction encryptString(str, passkey = null) {\n  if (typeof str !== 'string') {\n    throw new Error('Encrypt failed: invalid string');\n  }\n  if (str.length === 0) {\n    return '';\n  }\n\n  // If a passkey is provided (from cookies store), we must use it for encryption.\n  if (passkey !== null && passkey !== undefined) {\n    if (typeof passkey !== 'string' || passkey.length === 0) {\n      // Corrupted / empty passkey -> do not encrypt, return empty value\n      return '';\n    }\n    try {","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-electron/src/utils/encryption.js#L75-L111","documentation":"Thrown by safeStorageDecrypt when Electron's safeStorage.decryptString throws — i.e. the OS keychain (Keychain on macOS, DPAPI on Windows, libsecret on Linux) rejected the ciphertext. The blob was tagged ELECTRONSAFESTORAGE_ALGO ('$00:...') but the platform could not unlock it.","triggerScenarios":"OS credential store changed (password change, account switch, keychain reset); running on a different OS user than the one that encrypted; Linux libsecret backend unavailable; value was not actually produced by safeStorage but mis-tagged.","commonSituations":"User changed OS login password on Windows (DPAPI key tied to account); migrated to a new machine; Linux without gnome-keyring/kwallet; headless environment where safeStorage was available at encrypt time but not at decrypt time.","solutions":["Re-create the secret on the same OS user account that encrypted it; safeStorage values do not transfer across users/machines.","On Linux, ensure a libsecret service (gnome-keyring or kwallet) is running and unlocked.","Check safeStorage.isEncryptionAvailable() before relying on safeStorage values; re-prompt the user to re-enter if unavailable.","Use decryptStringSafe to convert this hard failure into a recoverable {success:false} in the UI."],"exampleFix":"// before\n} catch (err) {\n  console.error('SafeStorage decryption failed:', err);\n  throw new Error('SafeStorage decryption failed: ' + err.message);\n}\n\n// after: caller uses the safe wrapper\nfunction loadSecret(stored) {\n  const r = decryptStringSafe(stored);\n  return r.success ? r.value : null; // prompt user to re-enter\n}","handlingStrategy":"fallback","validationCode":"if (safeStorage && safeStorage.isEncryptionAvailable()) {\n  // safeStorage decrypt is permitted\n} else {\n  // re-prompt user; safeStorage values from another machine/user cannot be read here\n}","typeGuard":"function safeStorageUsable() {\n  return Boolean(safeStorage && safeStorage.isEncryptionAvailable());\n}","tryCatchPattern":"const { success, value } = decryptStringSafe(stored);\nif (!success) {\n  // OS keychain cannot unlock this value (cross-user/cross-machine/reset); re-enter secret\n  return await promptUserToReenterSecret();\n}","preventionTips":["safeStorage values are bound to the OS user account — never migrate them across users/machines.","On Linux, run gnome-keyring or kwallet and keep it unlocked.","Check isEncryptionAvailable() before relying on safeStorage-backed secrets."],"tags":["encryption","safe-storage","keychain","cross-machine"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}