Pular para o conteúdo principal

Tratamento de Erros

A Catalisa Platform utiliza códigos de status HTTP padrão e retorna mensagens de erro estruturadas em JSON.

Estrutura de Erro

{
"code": "NOT_FOUND",
"message": "User with id '123' not found",
"statusCode": 404,
"details": {
"resource": "User",
"id": "123"
}
}
CampoTipoDescrição
codestringCódigo do erro (constante)
messagestringMensagem legível do erro
statusCodeintegerCódigo HTTP do erro
detailsobjectDetalhes adicionais (opcional)

Códigos de Erro

400 - Bad Request (VALIDATION)

Erro de validação dos dados de entrada.

{
"code": "VALIDATION",
"message": "Validation failed",
"statusCode": 400,
"details": {
"email": "Invalid email format",
"password": "Password must be at least 8 characters"
}
}

Causas comuns:

  • Campos obrigatórios ausentes
  • Formato de dados inválido
  • Valores fora do range permitido

401 - Unauthorized (UNAUTHORIZED)

Falha na autenticação.

{
"code": "UNAUTHORIZED",
"message": "Invalid or expired token",
"statusCode": 401
}

Causas comuns:

  • Token ausente no header Authorization
  • Token expirado
  • Token inválido ou malformado

403 - Forbidden (FORBIDDEN)

Usuário autenticado, mas sem permissão para a operação.

{
"code": "FORBIDDEN",
"message": "Permission denied: USERS_DELETE required",
"statusCode": 403
}

Causas comuns:

  • Usuário sem a role necessária
  • Tentativa de acessar recurso de outra organização

404 - Not Found (NOT_FOUND)

Recurso não encontrado.

{
"code": "NOT_FOUND",
"message": "User with id 'abc-123' not found",
"statusCode": 404,
"details": {
"resource": "User",
"id": "abc-123"
}
}

Causas comuns:

  • ID inexistente
  • Recurso deletado
  • Recurso pertence a outra organização

409 - Conflict (CONFLICT)

Conflito com o estado atual do recurso.

{
"code": "CONFLICT",
"message": "User with email 'user@example.com' already exists",
"statusCode": 409,
"details": {
"field": "email"
}
}

Causas comuns:

  • Email/CPF já cadastrado
  • Slug/key duplicado
  • Violação de constraint único

500 - Internal Server Error (INTERNAL)

Erro interno do servidor.

{
"code": "INTERNAL",
"message": "Internal server error",
"statusCode": 500
}

Causas comuns:

  • Erro inesperado no servidor
  • Falha de conexão com banco de dados
  • Bug no sistema
aviso

Se você receber erros 500 frequentes, entre em contato com o suporte.

Tratamento de Erros

Exemplo Completo

class ApiError extends Error {
constructor(code, message, statusCode, details) {
super(message);
this.code = code;
this.statusCode = statusCode;
this.details = details;
}
}

async function apiRequest(url, options = {}) {
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers,
},
});

const data = await response.json();

if (!response.ok) {
throw new ApiError(
data.code,
data.message,
data.statusCode,
data.details
);
}

return data;
}

// Uso com tratamento de erros
try {
const user = await apiRequest('https://api.catalisa.io/iam/api/v1/users/123', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
console.log('Usuário:', user);
} catch (error) {
if (error instanceof ApiError) {
switch (error.code) {
case 'UNAUTHORIZED':
// Redirecionar para login ou renovar token
console.log('Token expirado, renovando...');
break;

case 'NOT_FOUND':
// Mostrar mensagem de recurso não encontrado
console.log('Usuário não encontrado');
break;

case 'VALIDATION':
// Mostrar erros de validação no formulário
console.log('Erros:', error.details);
break;

case 'FORBIDDEN':
// Mostrar mensagem de acesso negado
console.log('Você não tem permissão para esta ação');
break;

default:
// Erro generico
console.log('Erro:', error.message);
}
} else {
// Erro de rede ou outro
console.log('Erro de conexão');
}
}

Tratamento de Erros de Validação

async function createUser(email, password) {
try {
return await apiRequest('https://api.catalisa.io/iam/api/v1/users', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ email, password }),
});
} catch (error) {
if (error.code === 'VALIDATION') {
// Mapear erros para campos do formulário
const fieldErrors = {};

if (error.details) {
Object.entries(error.details).forEach(([field, message]) => {
fieldErrors[field] = message;
});
}

return { success: false, errors: fieldErrors };
}

throw error;
}
}

// Uso
const result = await createUser('invalid-email', '123');
if (!result.success) {
console.log('Erros de validação:', result.errors);
// { email: 'Invalid email format', password: 'Password must be at least 8 characters' }
}

Retry com Backoff Exponencial

Para erros transientes (5xx), implemente retry com backoff:

async function fetchWithRetry(url, options, maxRetries = 3) {
let lastError;

for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options);

if (response.ok) {
return response.json();
}

// Não fazer retry para erros 4xx
if (response.status < 500) {
const error = await response.json();
throw new ApiError(error.code, error.message, error.statusCode, error.details);
}

lastError = new Error(`HTTP ${response.status}`);
} catch (error) {
lastError = error;
}

// Backoff exponencial: 1s, 2s, 4s
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}

throw lastError;
}

Boas Práticas

Dicas
  1. Sempre verifique response.ok antes de processar a resposta
  2. Use o campo code para identificar o tipo de erro programaticamente
  3. Exiba message para usuários finais
  4. Log details para debugging
  5. Implemente retry apenas para erros 5xx
  6. Renove tokens automaticamente ao receber 401