diff --git a/src/App.test.tsx b/src/App.test.tsx
index ec5257dd..5f503023 100644
--- a/src/App.test.tsx
+++ b/src/App.test.tsx
@@ -495,6 +495,24 @@ describe('App', () => {
expect(screen.getByTestId('welcome-open-folder')).toHaveTextContent('Choose a different folder')
})
+ it('shows welcome instead of vault-missing when the missing path was not a persisted active vault', async () => {
+ localStorage.setItem('tolaria_welcome_dismissed', '1')
+ mockCommandResults.load_vault_list = {
+ vaults: [],
+ active_vault: null,
+ hidden_defaults: [],
+ }
+ mockCommandResults.check_vault_exists = (args?: { path?: string }) => args?.path === '/Users/mock/Documents/Getting Started'
+
+ render()
+
+ await waitFor(() => {
+ expect(screen.getByText('Welcome to Tolaria')).toBeInTheDocument()
+ })
+ expect(screen.queryByText('Vault not found')).not.toBeInTheDocument()
+ expect(screen.getByTestId('welcome-open-folder')).toHaveTextContent('Open existing vault')
+ })
+
it('renders sidebar with correct default selection (All Notes)', async () => {
render()
await waitFor(() => {
diff --git a/src/hooks/useOnboarding.test.ts b/src/hooks/useOnboarding.test.ts
index 486aeb26..0d93ed96 100644
--- a/src/hooks/useOnboarding.test.ts
+++ b/src/hooks/useOnboarding.test.ts
@@ -155,6 +155,21 @@ describe('useOnboarding', () => {
})
})
+ it('shows welcome instead of vault-missing when no persisted active vault matches the missing path', async () => {
+ localStorage.setItem(APP_STORAGE_KEYS.welcomeDismissed, '1')
+ mockCommands({
+ load_vault_list: {
+ vaults: [],
+ active_vault: null,
+ hidden_defaults: [],
+ },
+ })
+
+ const { result } = await renderOnboarding('/vault/deleted')
+
+ expect(result.current.state).toEqual({ status: 'welcome', defaultPath: DEFAULT_GETTING_STARTED_PATH })
+ })
+
it('clears the persisted active vault when the saved path no longer exists', async () => {
localStorage.setItem(LEGACY_APP_STORAGE_KEYS.welcomeDismissed, '1')
mockCommands({
diff --git a/src/hooks/useOnboarding.ts b/src/hooks/useOnboarding.ts
index 3ec6f231..d0a52367 100644
--- a/src/hooks/useOnboarding.ts
+++ b/src/hooks/useOnboarding.ts
@@ -40,10 +40,10 @@ function markDismissed(): void {
}
}
-async function clearMissingActiveVault(missingPath: string): Promise {
+async function clearMissingActiveVault(missingPath: string): Promise {
try {
const list = await tauriCall('load_vault_list', {})
- if (!list || list.active_vault !== missingPath) return
+ if (!list || list.active_vault !== missingPath) return false
await tauriCall('save_vault_list', {
list: {
vaults: list.vaults ?? [],
@@ -51,8 +51,10 @@ async function clearMissingActiveVault(missingPath: string): Promise {
hidden_defaults: list.hidden_defaults ?? [],
},
})
+ return true
} catch {
// Best effort only — onboarding should still proceed
+ return false
}
}
@@ -84,17 +86,14 @@ export function useOnboarding(
if (exists) {
setState({ status: 'ready', vaultPath: initialVaultPath })
- } else {
- await clearMissingActiveVault(initialVaultPath)
- if (cancelled) return
- }
-
- if (exists) {
return
}
- if (wasDismissed()) {
- // User previously dismissed — show vault-missing instead of welcome
+ const missingWasPersistedActiveVault = await clearMissingActiveVault(initialVaultPath)
+ if (cancelled) return
+
+ if (wasDismissed() && missingWasPersistedActiveVault) {
+ // Only show vault-missing when a previously selected vault path truly disappeared.
setState({ status: 'vault-missing', vaultPath: initialVaultPath, defaultPath })
} else {
setState({ status: 'welcome', defaultPath })