Clean errors

This commit is contained in:
Eric Bailey
2025-04-28 21:02:31 -05:00
parent f11b24e80e
commit e855ffc1c5
5 changed files with 111 additions and 7 deletions
@@ -4,6 +4,7 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {wait} from '#/lib/async/wait'
import {useCleanError} from '#/lib/hooks/useCleanError'
import {logger} from '#/logger'
import {useSession} from '#/state/session'
import {atoms as a, useTheme} from '#/alf'
@@ -86,6 +87,7 @@ function reducer(state: State, action: Action): State {
export function Disable() {
const t = useTheme()
const {_} = useLingui()
const cleanError = useCleanError()
const {currentAccount} = useSession()
const {mutateAsync: requestEmailUpdate} = useRequestEmailUpdate()
const {mutateAsync: manageEmail2FA} = useManageEmail2FA()
@@ -111,10 +113,10 @@ export function Disable() {
logger.error('Manage2FA: email update code request failed', {
safeMessage: e,
})
// TODO rate limit
const {clean} = cleanError(e)
dispatch({
type: 'setError',
error: _(msg`Failed to send email, please try again.`),
error: clean || _(msg`Failed to send email, please try again.`),
})
}
}
@@ -130,9 +132,10 @@ export function Disable() {
}, 1000)
} catch (e) {
logger.error('Manage2FA: disable email 2FA failed', {safeMessage: e})
const {clean} = cleanError(e)
dispatch({
type: 'setError',
error: _(msg`Update to email 2FA settings failed`),
error: clean || _(msg`Update to email 2FA settings failed`),
})
}
}
@@ -4,6 +4,7 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {wait} from '#/lib/async/wait'
import {useCleanError} from '#/lib/hooks/useCleanError'
import {logger} from '#/logger'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Admonition} from '#/components/Admonition'
@@ -55,6 +56,7 @@ function reducer(state: State, action: Action): State {
export function Enable() {
const t = useTheme()
const {_} = useLingui()
const cleanError = useCleanError()
const {gtPhone} = useBreakpoints()
const {mutateAsync: manageEmail2FA} = useManageEmail2FA()
const control = useDialogContext()
@@ -75,9 +77,10 @@ export function Enable() {
}, 1000)
} catch (e) {
logger.error('Manage2FA: enable email 2FA failed', {safeMessage: e})
const {clean} = cleanError(e)
dispatch({
type: 'setError',
error: _(msg`Update to email 2FA settings failed`),
error: clean || _(msg`Update to email 2FA settings failed`),
})
}
}
@@ -5,6 +5,7 @@ import {useLingui} from '@lingui/react'
import {validate as validateEmail} from 'email-validator'
import {wait} from '#/lib/async/wait'
import {useCleanError} from '#/lib/hooks/useCleanError'
import {logger} from '#/logger'
import {useSession} from '#/state/session'
import {atoms as a, useTheme} from '#/alf'
@@ -102,6 +103,7 @@ function reducer(state: State, action: Action): State {
export function Update(_props: ScreenProps<ScreenID.Update>) {
const t = useTheme()
const {_} = useLingui()
const cleanError = useCleanError()
const {currentAccount} = useSession()
const [state, dispatch] = useReducer(reducer, {
step: 'email',
@@ -176,9 +178,10 @@ export function Update(_props: ScreenProps<ScreenID.Update>) {
}
} catch (e) {
logger.error('EmailDialog: update email failed', {safeMessage: e})
const {clean} = cleanError(e)
dispatch({
type: 'setError',
error: _(msg`Email updated failed, please try again.`),
error: clean || _(msg`Email updated failed, please try again.`),
})
}
}
@@ -4,6 +4,7 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {wait} from '#/lib/async/wait'
import {useCleanError} from '#/lib/hooks/useCleanError'
import {logger} from '#/logger'
import {useSession} from '#/state/session'
import {atoms as a, useTheme} from '#/alf'
@@ -87,6 +88,7 @@ function reducer(state: State, action: Action): State {
export function Verify({config}: ScreenProps<ScreenID.Verify>) {
const t = useTheme()
const {_} = useLingui()
const cleanError = useCleanError()
const {currentAccount} = useSession()
const [state, dispatch] = useReducer(reducer, {
step: 'email',
@@ -125,9 +127,10 @@ export function Verify({config}: ScreenProps<ScreenID.Verify>) {
logger.error('EmailDialog: sending verification email failed', {
safeMessage: e,
})
const {clean} = cleanError(e)
dispatch({
type: 'setError',
error: _(msg`Failed to send email, please try again.`),
error: clean || _(msg`Failed to send email, please try again.`),
})
}
}
@@ -148,9 +151,10 @@ export function Verify({config}: ScreenProps<ScreenID.Verify>) {
logger.error('EmailDialog: confirming email failed', {
safeMessage: e,
})
const {clean} = cleanError(e)
dispatch({
type: 'setError',
error: _(msg`Failed to verify email, please try again.`),
error: clean || _(msg`Failed to verify email, please try again.`),
})
}
}
+91
View File
@@ -0,0 +1,91 @@
import {useCallback} from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
type CleanedError = {
raw: string | undefined
clean: string | undefined
}
export function useCleanError() {
const {_} = useLingui()
return useCallback<(error?: any) => CleanedError>(
error => {
if (!error)
return {
raw: undefined,
clean: undefined,
}
let raw = error.toString()
if (isNetworkError(raw)) {
return {
raw,
clean: _(
msg`Unable to connect. Please check your internet connection and try again.`,
),
}
}
if (
raw.includes('Upstream Failure') ||
raw.includes('NotEnoughResources') ||
raw.includes('pipethrough network error')
) {
return {
raw,
clean: _(
msg`The server appears to be experiencing issues. Please try again in a few moments.`,
),
}
}
if (raw.includes('Bad token scope')) {
return {
raw,
clean: _(
msg`This feature is not available while using an App Password. Please sign in with your main password.`,
),
}
}
if (raw.includes('Rate Limit Exceeded')) {
return {
raw,
clean: _(
msg`You've reached the maximum number of requests allowed. Please try again later.`,
),
}
}
if (raw.startsWith('Error: ')) {
raw = raw.slice('Error: '.length)
}
return {
raw,
clean: undefined,
}
},
[_],
)
}
const NETWORK_ERRORS = [
'Abort',
'Network request failed',
'Failed to fetch',
'Load failed',
]
export function isNetworkError(e: unknown) {
const str = String(e)
for (const err of NETWORK_ERRORS) {
if (str.includes(err)) {
return true
}
}
return false
}