chatboxai/chatbox · warning · Error
Failed to send login code
Error message
Failed to send login code
What it means
Thrown by sendCode when sendEmailLoginCode resolves with any value other than the literal 'sent'. The login-code endpoint is expected to acknowledge success with 'sent'; any other payload is treated as a rejection. The throw is caught immediately and converted to a user-facing loginError, so it is a control-flow signal more than a crash.
Source
Thrown at src/renderer/routes/settings/provider/chatbox-ai/-components/useLogin.ts:116
return false
}
try {
setLoginState('sending_code')
setLoginError('')
setCode('')
const result = await sendEmailLoginCode({
email: trimmedEmail,
lang: getLanguagePath(language),
})
if (requestEpoch !== requestEpochRef.current) {
return false
}
if (result !== 'sent') {
throw new Error('Failed to send login code')
}
setLoginState('code_sent')
setHasEnteredCodeStep(true)
setCountdown(EMAIL_CODE_RESEND_SECONDS)
return true
} catch (error: unknown) {
if (requestEpoch !== requestEpochRef.current) {
return false
}
console.error('Failed to send login code:', error)
const errorMsg = getReadableErrorMessage(error, t('Failed to send login code'))
setLoginError(errorMsg)
setLoginState('error')
return false
}
}, [email, language, t])View on GitHub (pinned to 81571269ad)
Solutions
- Differentiate non-'sent' values: map known backend reasons (rate_limited, invalid_email) to specific UI messages instead of a generic throw.
- Confirm the sendEmailLoginCode return contract matches the backend (string 'sent' vs object).
- Throttle the send button with the EMAIL_CODE_RESEND_SECONDS countdown before the request fires.
- Log the actual returned value (redacted) to identify contract drift.
Example fix
// before
if (result !== 'sent') {
throw new Error('Failed to send login code')
}
// after
if (result !== 'sent') {
const reason = typeof result === 'string' ? result : 'unknown'
throw new Error(`Failed to send login code: ${reason}`)
} Defensive patterns
Strategy: validation
Validate before calling
const result = await sendEmailLoginCode({ email: trimmedEmail, lang: getLanguagePath(language) })
if (result !== 'sent') {
// result carries the backend reason; map it before throwing
} Type guard
type SendCodeResult = 'sent' | 'rate_limited' | 'invalid_email' | 'unknown'
function isSendSuccess(r: unknown): r is 'sent' {
return r === 'sent'
} Try / catch
try {
const result = await sendEmailLoginCode(...)
if (!isSendSuccess(result)) setLoginError(mapSendCodeResult(result))
} catch (error) {
setLoginError(getReadableErrorMessage(error, t('Failed to send login code')))
} Prevention
- Throttle the send button with EMAIL_CODE_RESEND_SECONDS before firing the request.
- Map known backend reason strings to specific UI messages.
- Validate email format client-side before the request.
When it happens
Trigger: sendEmailLoginCode returns a non-'sent' string — backend-reported reasons such as rate limiting, invalid/unknown email, banned account, or an undocumented status. Also fires if the endpoint payload shape changes (e.g. returns { status: 'sent' }) so the strict equality check fails.
Common situations: User clicks 'send code' repeatedly and hits server-side rate limiting, email is malformed in a way the client regex allowed, backend deploy changes the response contract, or the account is flagged.
Related errors
- Knowledge base ${kbId} not found
- email required
- No content extracted from file
- Failed to search knowledge base (id: ${kbId}). Please try ag
- Invalid pagination parameters
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/8729d8e8cd80a25a.
Report an issue: GitHub.