tinyhumansai/openhuman · error
Failed to secure recovery phrase. Please try again.
Error message
Failed to secure recovery phrase. Please try again.
What it means
Later in setupLocalWalletFromMnemonic(): the phrase was accepted and the renderer asks the core to encrypt it via openhumanEncryptSecret(normalizedMnemonic). The call returns an object whose result should be a trimmed non-empty ciphertext; if it comes back empty/undefined the flow throws 'Failed to secure recovery phrase. Please try again.' — i.e. the core-side encryption step failed silently.
Solutions
- Retry once — transient keychain locks (especially right after login on macOS) can clear; the message itself says 'Please try again'.
- Check OS keychain/secret-service health: on Linux ensure gnome-keyring or kwallet is running; on macOS unlock the login keychain; on Windows check Credential Manager permissions.
- Verify core and app versions match (partial updates can skew RPC response shapes) — update or restart both.
- Inspect core logs for the encrypt-secret handler's error to find the underlying keyring failure; enable the keyring consent flow if prompted.
Example fix
// before
const encryptedMnemonic = (await openhumanEncryptSecret(normalizedMnemonic)).result?.trim();
if (!encryptedMnemonic) throw new Error('Failed to secure recovery phrase. Please try again.');
// after — retry once before failing
let encryptedMnemonic: string | undefined;
for (let attempt = 0; attempt < 2 && !encryptedMnemonic; attempt++) {
encryptedMnemonic = (await openhumanEncryptSecret(normalizedMnemonic)).result?.trim();
}
if (!encryptedMnemonic) throw new Error('Failed to secure recovery phrase. Please try again.'); Defensive patterns
Strategy: retry
Try / catch
try {
await setupLocalWalletFromMnemonic(args);
} catch (err) {
if (err instanceof Error && err.message.startsWith('Failed to secure recovery phrase')) {
// keychain may be transiently locked — prompt retry once
if (await askUserToRetry()) return setupLocalWalletFromMnemonic(args);
}
throw err;
} Prevention
- Ensure the OS keyring/secret service is available before starting wallet setup (surface a preflight warning on minimal Linux).
- Keep core and app versions matched to avoid RPC response-shape skew.
- Log the raw openhumanEncryptSecret response in dev to distinguish empty result from transport error.
When it happens
Trigger: The openhumanEncryptSecret RPC resolves but with an empty result: core keyring/encryption unavailable (OS keychain locked or denied), an error payload swallowed by the RPC wrapper, or a core version whose encrypt-secret response shape differs (result field renamed) so .result?.trim() yields undefined.
Common situations: OS keychain access denied (macOS Keychain, Windows Credential Manager, Linux secret service absent in minimal WMs) so the core cannot create the encryption key; core/renderer version skew after a partial update; headless/Linux environments without a secrets service where the keyring backend fails.
Related errors
- Recovery phrase is required.
- At least one of --expression, --tz, --command, or --name…
- Core rejected the agent_meetings_join request.
- Core rejected the meet_agent_get_call_detail request.
- Core rejected the meet_agent_list_calls request.
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/5bd1ee1570a1b081.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/features/wallet/setupLocalWalletFromMnemonic.ts:28
mnemonic: string;
source: WalletSetupSource;
setEncryptionKey: (value: string | null) => Promise<void>;
/**
* Set to `true` only when the user has explicitly confirmed wallet replacement
* through the double-confirmation dialog. Defaults to `false`.
*/
force?: boolean;
}): Promise<void> {
const { mnemonic, source, setEncryptionKey, force } = args;
const words = mnemonic.trim().split(/\s+/).filter(Boolean);
if (words.length === 0) {
throw new Error('Recovery phrase is required.');
}
const normalizedMnemonic = words.join(' ');
const aesKey = deriveAesKeyFromMnemonic(normalizedMnemonic);
const encryptedMnemonic = (await openhumanEncryptSecret(normalizedMnemonic)).result?.trim();
if (!encryptedMnemonic) {
throw new Error('Failed to secure recovery phrase. Please try again.');
}
await setEncryptionKey(aesKey);
await setupLocalWallet({
consentGranted: true,
source,
mnemonicWordCount: words.length,
encryptedMnemonic,
accounts: deriveWalletAccountsFromMnemonic(normalizedMnemonic),
force,
});
}
View on GitHub (pinned to 7491200858)