Keep the DeleteAccountDialog guard inside the try

Addresses review feedback on #11545. Hoisting the guard above the try moved the
throw past the catch, so a falsy did became an unhandled rejection with no
inline error, no log and no step reset.

Reverting outright would re-break compilation - confirmDeletion is a nested
callback of the component, so its throw is part of the same compiled unit. The
check stays where it was; only the throw and the optional chain move to a
module-scope requireAccount.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tomek Zawadzki
2026-08-25 17:35:15 +02:00
parent 5fa9e3cc1c
commit e991e3f64f
@@ -8,6 +8,7 @@ import {useCleanError} from '#/lib/hooks/useCleanError'
import {sanitizeHandle} from '#/lib/strings/handles'
import {logger} from '#/logger'
import {
type SessionAccount,
useChatClient,
usePdsClient,
useSession,
@@ -49,6 +50,17 @@ function isPasswordValid(password: string) {
return password.length >= PASSWORD_MIN_LENGTH
}
/**
* Out of the component because React Compiler cannot lower a `throw`, or the
* optional chain in this check, inside a `try`. Keeping the check in the `try` -
* rather than hoisting it above - means the catch below still runs: inline
* error, log, and reset to the code step.
*/
function requireAccount(account: SessionAccount | undefined): SessionAccount {
if (!account?.did) throw new Error('Invalid did')
return account
}
export function DeleteAccountDialog({
control,
deactivateDialogControl,
@@ -111,11 +123,9 @@ function DeleteAccountDialogInner({
}, [client, cleanError, emailState, setEmailState])
const confirmDeletion = useCallback(async () => {
if (!currentAccount?.did) {
throw new Error('Invalid did')
}
try {
setError('')
const account = requireAccount(currentAccount)
const token = confirmCode.replace(WHITESPACE_RE, '')
/*
* Inform chat service of intent to delete account. A non-2xx response
@@ -124,14 +134,14 @@ function DeleteAccountDialogInner({
*/
await chatClient.call(chat.bsky.actor.deleteAccount)
await client.call(com.atproto.server.deleteAccount, {
did: currentAccount.did,
did: account.did,
password,
token,
})
control.close(() => {
toast.show(_(msg`Your account has been deleted, see ya! ✌️`))
resetToTab('HomeTab')
removeAccount(currentAccount)
removeAccount(account)
})
} catch (e: any) {
const {clean, raw} = cleanError(e)