From cf7350b21014244b59109636da08fa39cc56398e Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Sun, 26 Apr 2026 22:07:44 +0200 Subject: [PATCH] Detect vault locked error and redirect to vault unlock instead of showing error --- apps/mobile-app/app/vault-error.tsx | 19 ++++++++++++++++++- .../utils/types/errors/AppErrorCodes.ts | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/apps/mobile-app/app/vault-error.tsx b/apps/mobile-app/app/vault-error.tsx index f6795f4b3..9e3f22bf9 100644 --- a/apps/mobile-app/app/vault-error.tsx +++ b/apps/mobile-app/app/vault-error.tsx @@ -1,10 +1,11 @@ import { MaterialIcons } from '@expo/vector-icons'; import { LinearGradient } from 'expo-linear-gradient'; import { router, useLocalSearchParams } from 'expo-router'; -import { useState, useCallback } from 'react'; +import { useState, useCallback, useEffect } from 'react'; import { StyleSheet, View, ScrollView, Dimensions, Text, Platform } from 'react-native'; import { copyToClipboard } from '@/utils/ClipboardUtility'; +import { isVaultLockedError } from '@/utils/types/errors/AppErrorCodes'; import { useColors } from '@/hooks/useColorScheme'; import { useLogout } from '@/hooks/useLogout'; @@ -31,6 +32,18 @@ export default function VaultErrorScreen() : React.ReactNode { const [showDetails, setShowDetails] = useState(false); const [copied, setCopied] = useState(false); + /* + * Central safety net: if the error indicates the in-memory vault was cleared + * (auto-lock timeout), redirect to the reinitialize flow instead of showing + * the fatal-error screen. + */ + const shouldReinitialize = isVaultLockedError(errorMessage) && errorSource !== 'reinitialize'; + useEffect(() => { + if (shouldReinitialize) { + router.replace('/reinitialize'); + } + }, [shouldReinitialize]); + /** * Copy the full error details to clipboard for sharing with support. */ @@ -56,6 +69,10 @@ export default function VaultErrorScreen() : React.ReactNode { router.replace('/initialize'); }, []); + if (shouldReinitialize) { + return null; + } + const styles = StyleSheet.create({ appName: { color: colors.text, diff --git a/apps/mobile-app/utils/types/errors/AppErrorCodes.ts b/apps/mobile-app/utils/types/errors/AppErrorCodes.ts index d734e540e..f20e92caf 100644 --- a/apps/mobile-app/utils/types/errors/AppErrorCodes.ts +++ b/apps/mobile-app/utils/types/errors/AppErrorCodes.ts @@ -135,6 +135,20 @@ export function getAppErrorCode(error: unknown): AppErrorCode | null { return null; } +/** + * Detect a "vault locked" error — i.e. the in-memory database has been cleared + * (auto-lock timeout, vault evicted from memory). + */ +export function isVaultLockedError(error: unknown): boolean { + const message = + error instanceof Error + ? error.message + : typeof error === 'string' + ? error + : ''; + return message.includes('Database not initialized'); +} + /** * Extract error code from a string (e.g., "Error occurred (Code: E-501)" -> "E-501") */