Tratando erros
Quais falhas o seu código repete, quais precisam do usuário, e quais são suas para corrigir.
Toda falha chega no mesmo formato, então a pergunta interessante não é como ler uma — a referência cobre isso — mas o que fazer com ela.
Só existem quatro respostas, e o status_code diz qual se aplica antes de você
sequer olhar o code.
Ramifique primeiro pelo status
400, 413, 422Bug seuA requisição estava malformada ou os dados foram rejeitados. Repetir não muda nada.
401Entrar de novoSem sessão válida. Mande para a tela de entrada, não para uma tela de erro.
403Pedir algo ao usuárioAutenticado, mas falta uma permissão, uma confirmação ou um segundo fator.
429, 503Esperar e repetirNão há nada errado com a requisição. Recue.
Só então o code importa — ele diz qual dessas, para você escrever uma
mensagem útil em vez de "algo deu errado".
const { data, error } = await nulvless.auth.signIn({ email, password });
if (error) {
if (error.status_code === 401) return goToSignIn();
if (error.status_code === 429) return backOff(error);
return showMessage(messageFor(error.code) ?? error.message);
}A família 403 é a interessante
Um 403 quase nunca significa "desista". Significa que o usuário pode fazer algo a
respeito, e o code diz o quê:
protected_action_deniedConfirmar identidadeModo sudo é exigido. Inicie o fluxo de sudo e repita.
mfa_requiredCadastrar um fatorO ambiente exige MFA e esta sessão nunca usou um.
user_not_confirmedConcluir o cadastroO endereço ou telefone nunca foi confirmado.
forbidden_access_waiting_acceptAceitar o conviteExiste um grant, mas ainda pendente — está na caixa de entrada da pessoa.
forbidden_resource_accessRealmente não permitidoSem grant no recurso, ou falta um escopo ou papel.
Juntar todos numa única tela de "Acesso negado" é o erro mais comum, e deixa travada gente que estava a um clique de continuar.
Deixe os eventos cuidarem do sudo
O protected_action_denied é comum o bastante para o SDK emitir um evento, então
você não precisa capturá-lo em cada ponto de chamada:
nulvless.auth.on('sudo-required', async () => {
await nulvless.auth.sessions.sudo();
openSudoPrompt();
});Existe também um evento unauthorized para o caso do 401. Veja
Events.
Recuando
Dois códigos significam "agora não":
if (error.code === 'rate_limit_exceeded' || error.code === 'service_overloaded') {
await wait(backoff());
}O SDK não expõe o Retry-After
O NulvlessError carrega exatamente três campos — code, message e
status_code. O serviço de auth até coloca um retryAfter no corpo da resposta
de limite, e o service_overloaded vem com um header Retry-After, mas nenhum
dos dois sobrevive até o objeto de erro. Use o seu próprio backoff, ou leia a
resposta crua se precisar da dica.
Nunca repita um 400, 413 ou 422. A requisição vai falhar igual toda vez.
Erros de validação chegam em lista
message é string | string[] — um array quando vários campos falharam de uma
vez. Achate isso num lugar só:
const text = Array.isArray(error.message) ? error.message.join(', ') : error.message;O cadastro é onde você encontra isso primeiro: uma requisição pode ser rejeitada pelo e-mail e pelo telefone na mesma resposta.
Mostre o código quando não souber explicar
Para o que você não escreveu mensagem, mostrar o code cru é melhor que um pedido
de desculpas genérico — é o que o seu time de suporte vai pedir, e é estável entre
versões de um jeito que o texto da mensagem não é.
A plataforma anexa um reference a uma falha de deploy não classificada
(internal_error) para o suporte achar a linha de log. Como o retryAfter, ele
está no corpo da resposta e não no NulvlessError, então recorra à resposta crua
se quiser exibi-lo.
Alguns erros nunca chegam à rede
Alguns códigos são produzidos pelo próprio SDK, antes ou no lugar de uma requisição. Têm o mesmo formato, então a mesma ramificação atende:
no_session401Uma chamada que precisa de sessão rodou sem nenhuma guardada.
request_timeout408O timeout que você configurou estourou.
network_error0A requisição nunca completou. status_code é 0 — nada respondeu.
unknown_errorChegou uma resposta que não foi interpretada como payload de erro.
status_code: 0 é o teste confiável para "offline ou inalcançável", e merece
mensagem própria.
Edge functions respondem 546
Se você chama uma edge function do seu próprio código, três falhas chegam com status 546, não com um 5xx que você reconheceria:
if (response.status === 546) {
const { code } = await response.json();
// execution_timeout | cpu_time_limit_exceeded | memory_limit_exceeded
}É deliberadamente fora da faixa padrão, para uma violação de limite nunca ser
confundida com erro de servidor. Um 500 puro, sem code no corpo significa o
oposto — a sua função lançou, e a plataforma não está afirmando saber por quê.
Os códigos têm escopo por serviço
A mesma string pode estar definida em mais de um serviço, e o código que você vê
depende de quem respondeu. O unauthorized do serviço de auth e o unauthorized
da API da plataforma querem dizer a mesma coisa em espírito, mas são definições
separadas.
A página de Códigos de exceção lista por escopo, e só os que estão de fato em uso.