Códigos de Erro
Referência completa de códigos de erro e como resolver cada um
Códigos de Erro
Guia completo de todos os códigos de erro da API RenderHub, com exemplos e soluções.
Formato de Erro
Todos os erros seguem o mesmo formato JSON:
{
"error": "error_code",
"message": "Descrição legível do erro",
"code": 400,
"field": "campo_especifico",
"details": "Informações adicionais"
}
Códigos HTTP
| Código | Nome | Significado |
|---|---|---|
200 | OK | Requisição bem-sucedida |
400 | Bad Request | Requisição inválida |
401 | Unauthorized | Autenticação falhou |
403 | Forbidden | Sem permissão ou quota excedida |
404 | Not Found | Recurso não encontrado |
413 | Payload Too Large | Conteúdo muito grande |
422 | Unprocessable Entity | Erro ao processar conteúdo |
429 | Too Many Requests | Rate limit excedido |
500 | Internal Server Error | Erro interno do servidor |
503 | Service Unavailable | Serviço temporariamente indisponível |
Erros de Autenticação (401)
missing_authorization
Cabeçalho Authorization ausente na requisição.
{
"error": "missing_authorization",
"message": "Cabeçalho Authorization é obrigatório",
"code": 401
}
Solução:
// ❌ Erro
fetch('/api/v1/render', {
method: 'POST',
body: JSON.stringify(data)
});
// ✅ Correto
fetch('/api/v1/render', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify(data)
});
invalid_api_key
Chave de API inválida ou mal formatada.
{
"error": "invalid_api_key",
"message": "Chave de API inválida",
"code": 401
}
Causas comuns:
- Chave copiada incorretamente (espaços extras)
- Prefixo
Bearerausente - Chave de teste usada em produção (ou vice-versa)
Solução:
// ✅ Verifique o formato correto
const API_KEY = 'rh_live_abc123...'; // Deve começar com rh_live_ ou rh_test_
headers: {
'Authorization': `Bearer ${API_KEY}` // Não esqueça do "Bearer "
}
revoked_api_key
Chave de API foi revogada.
{
"error": "revoked_api_key",
"message": "Esta chave de API foi revogada",
"revoked_at": "2024-01-15T10:00:00Z",
"code": 401
}
Solução: Crie uma nova chave de API no Dashboard.
expired_api_key
Chave de API expirou (apenas chaves temporárias).
{
"error": "expired_api_key",
"message": "Chave de API expirou em 2024-01-01",
"expired_at": "2024-01-01T00:00:00Z",
"code": 401
}
Solução: Gere uma nova chave permanente.
Erros de Permissão (403)
quota_exceeded
Quota mensal de requisições excedida.
{
"error": "quota_exceeded",
"message": "Quota mensal de 1.000 requisições excedida",
"quota_limit": 1000,
"quota_used": 1000,
"quota_reset": "2024-02-01T00:00:00Z",
"code": 403
}
Soluções:
- Aguarde o reset mensal
- Faça upgrade do plano
- Otimize uso com cache
insufficient_permissions
Chave de API não tem permissão para esta ação.
{
"error": "insufficient_permissions",
"message": "Esta chave não tem permissão para deletar templates",
"required_permission": "templates:delete",
"code": 403
}
Solução: Use uma chave com permissões adequadas ou crie uma nova no Dashboard.
account_suspended
Conta suspensa por violação de termos ou pagamento pendente.
{
"error": "account_suspended",
"message": "Sua conta foi suspensa. Entre em contato com o suporte.",
"suspended_at": "2024-01-15T10:00:00Z",
"reason": "payment_overdue",
"code": 403
}
Solução: Entre em contato com support@renderhub.com
Erros de Validação (400)
invalid_request
Requisição mal formatada ou campos obrigatórios ausentes.
{
"error": "invalid_request",
"message": "O campo 'mode' é obrigatório",
"field": "mode",
"code": 400
}
Exemplos comuns:
// ❌ Modo ausente
{ input_type: 'html', data: '<h1>Test</h1>' }
// ✅ Correto
{ mode: 'CONVERT', input_type: 'html', data: '<h1>Test</h1>' }
// ❌ input_type inválido
{ mode: 'CONVERT', input_type: 'pdf', data: '...' }
// ✅ Correto
{ mode: 'CONVERT', input_type: 'html', data: '...' }
invalid_mode
Modo de operação inválido.
{
"error": "invalid_mode",
"message": "Modo deve ser 'CONVERT' ou 'RENDER'",
"received": "TRANSFORM",
"valid_values": ["CONVERT", "RENDER"],
"code": 400
}
invalid_input_type
Tipo de entrada não suportado.
{
"error": "invalid_input_type",
"message": "Tipo de entrada inválido: 'pdf'",
"received": "pdf",
"valid_values": ["html", "docx", "markdown", "xml", "csv", "json"],
"code": 400
}
invalid_page_size
Tamanho de página inválido.
{
"error": "invalid_page_size",
"message": "Tamanho de página inválido: 'custom'",
"received": "custom",
"valid_values": ["A4", "A3", "Letter", "Legal", "Tabloid"],
"code": 400
}
invalid_orientation
Orientação inválida.
{
"error": "invalid_orientation",
"message": "Orientação deve ser 'portrait' ou 'landscape'",
"received": "horizontal",
"code": 400
}
missing_template_id
Template ID ausente no modo RENDER.
{
"error": "missing_template_id",
"message": "template_id é obrigatório no modo RENDER",
"code": 400
}
Solução:
// ✅ Correto
{
mode: 'RENDER',
template_id: 'tpl_invoice_001',
data: { ... }
}
missing_data
Campo data ausente no modo CONVERT.
{
"error": "missing_data",
"message": "Campo 'data' é obrigatório no modo CONVERT",
"code": 400
}
Erros de Conteúdo (422)
conversion_failed
Falha ao converter conteúdo para PDF.
{
"error": "conversion_failed",
"message": "Falha ao converter HTML para PDF",
"details": "CSS inválido na linha 15: unexpected token '}'",
"line": 15,
"code": 422
}
Causas comuns:
- HTML malformado
- CSS inválido
- JavaScript com erros
- Imagens quebradas
Solução: Valide seu HTML/CSS antes de enviar:
// Valide HTML básico
const isValid = html.includes('<html>') && html.includes('</html>');
invalid_html
HTML malformado ou inválido.
{
"error": "invalid_html",
"message": "HTML malformado: tag não fechada",
"details": "Unclosed tag <div> at line 42",
"line": 42,
"code": 422
}
invalid_docx
Arquivo DOCX corrompido ou inválido.
{
"error": "invalid_docx",
"message": "Arquivo DOCX inválido ou corrompido",
"details": "Failed to parse DOCX: invalid ZIP archive",
"code": 422
}
Solução: Verifique se o arquivo está corrompido e se está codificado em base64 corretamente.
invalid_markdown
Markdown com sintaxe inválida.
{
"error": "invalid_markdown",
"message": "Markdown inválido: bloco de código não fechado",
"line": 25,
"code": 422
}
template_not_found
Template especificado não existe.
{
"error": "template_not_found",
"message": "Template 'tpl_invoice_999' não encontrado",
"template_id": "tpl_invoice_999",
"code": 422
}
Solução: Verifique o ID do template no Dashboard.
template_render_error
Erro ao renderizar template com dados fornecidos.
{
"error": "template_render_error",
"message": "Falha ao renderizar template: variável 'customer_name' não encontrada",
"missing_variable": "customer_name",
"code": 422
}
Solução: Certifique-se de que todos os campos do template estão no JSON:
// Template usa: {{customer_name}}, {{total}}
// ❌ Dados incompletos
{ total: '100' }
// ✅ Dados completos
{ customer_name: 'João', total: '100' }
image_load_failed
Falha ao carregar imagem externa.
{
"error": "image_load_failed",
"message": "Falha ao carregar imagem: https://exemplo.com/logo.png",
"image_url": "https://exemplo.com/logo.png",
"reason": "DNS resolution failed",
"code": 422
}
Soluções:
- Use imagens base64 inline
- Verifique se a URL está acessível
- Use HTTPS para imagens
Erros de Tamanho (413)
payload_too_large
Payload excede o tamanho máximo.
{
"error": "payload_too_large",
"message": "Tamanho do payload excede 10 MB",
"max_size_mb": 10,
"received_size_mb": 15.2,
"code": 413
}
Soluções:
- Comprima imagens antes de incorporar
- Use referências externas para imagens grandes
- Divida em múltiplos PDFs
- Faça upgrade para plano Enterprise (50 MB)
pdf_too_large
PDF gerado excede o tamanho máximo.
{
"error": "pdf_too_large",
"message": "PDF gerado excede 50 MB",
"max_size_mb": 50,
"generated_size_mb": 67,
"code": 413
}
Soluções:
- Reduza qualidade de imagens
- Remova imagens de fundo desnecessárias
- Divida em múltiplos PDFs
Erros de Rate Limit (429)
rate_limit_exceeded
Limite de requisições por minuto excedido.
{
"error": "rate_limit_exceeded",
"message": "Você excedeu 20 requisições por minuto",
"limit": 20,
"retry_after": 45,
"reset_at": "2024-01-15T10:31:00Z",
"code": 429
}
Solução: Implemente retry com backoff exponencial:
async function generatePDFWithRetry(data, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await axios.post('/api/v1/render', data);
} catch (error) {
if (error.response?.status === 429) {
const retryAfter = error.response.data.retry_after || (2 ** i);
console.log(`Rate limited. Aguardando ${retryAfter}s...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
} else {
throw error;
}
}
}
throw new Error('Máximo de tentativas atingido');
}
Erros de Servidor (500)
internal_error
Erro interno do servidor.
{
"error": "internal_error",
"message": "Erro interno ao processar requisição",
"request_id": "req_abc123",
"code": 500
}
Solução:
- Tente novamente em alguns segundos
- Se persistir, entre em contato com o suporte informando o
request_id
service_unavailable
Serviço temporariamente indisponível.
{
"error": "service_unavailable",
"message": "Serviço temporariamente indisponível para manutenção",
"retry_after": 300,
"code": 503
}
Solução: Aguarde o tempo indicado em retry_after (segundos).
Erros de Timeout
processing_timeout
Processamento excedeu o tempo limite.
{
"error": "processing_timeout",
"message": "Processamento excedeu 30 segundos",
"timeout_seconds": 30,
"code": 422
}
Soluções:
- Simplifique o HTML (menos JavaScript)
- Reduza número de imagens
- Use modo assíncrono com webhook
- Upgrade para Enterprise (60s timeout)
javascript_timeout
JavaScript excedeu tempo de execução.
{
"error": "javascript_timeout",
"message": "Execução de JavaScript excedeu 5 segundos",
"timeout_seconds": 5,
"code": 422
}
Solução: Otimize scripts ou remova JavaScript desnecessário.
Erros de Webhook
webhook_failed
Falha ao enviar callback para webhook.
{
"error": "webhook_failed",
"message": "Falha ao enviar callback: Connection refused",
"webhook_url": "https://meuapp.com/webhook",
"attempts": 3,
"last_error": "ECONNREFUSED",
"code": 500
}
Solução: Verifique se a URL do webhook está acessível e aceitando POST.
Tratamento de Erros
Estratégia Recomendada
async function generatePDF(data) {
try {
const response = await axios.post('/api/v1/render', data, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
return response.data;
} catch (error) {
if (error.response) {
const { status, data } = error.response;
switch (status) {
case 400:
console.error('Requisição inválida:', data.message);
// Corrigir dados e tentar novamente
break;
case 401:
console.error('Erro de autenticação:', data.message);
// Verificar chave de API
break;
case 403:
if (data.error === 'quota_exceeded') {
console.error('Quota excedida. Reset em:', data.quota_reset);
// Notificar usuário ou fazer upgrade
}
break;
case 413:
console.error('Payload muito grande:', data.message);
// Reduzir tamanho ou dividir em partes
break;
case 422:
console.error('Erro ao processar:', data.message);
console.error('Detalhes:', data.details);
// Corrigir conteúdo
break;
case 429:
console.log('Rate limit. Aguardando', data.retry_after, 'segundos');
// Implementar retry
await sleep(data.retry_after * 1000);
return generatePDF(data); // Tentar novamente
break;
case 500:
case 503:
console.error('Erro do servidor:', data.message);
console.error('Request ID:', data.request_id);
// Tentar novamente ou contatar suporte
break;
default:
console.error('Erro desconhecido:', data);
}
} else {
console.error('Erro de rede:', error.message);
}
throw error;
}
}
Logging de Erros
function logError(error) {
const errorData = {
timestamp: new Date().toISOString(),
error_code: error.response?.data?.error,
message: error.response?.data?.message,
request_id: error.response?.data?.request_id,
status: error.response?.status,
stack: error.stack
};
// Enviar para serviço de logging (Sentry, LogRocket, etc.)
console.error('PDF Generation Error:', JSON.stringify(errorData, null, 2));
}
Monitoramento
Use os cabeçalhos de resposta para monitorar limites:
function checkRateLimits(response) {
const remaining = response.headers['x-ratelimit-remaining'];
const quotaRemaining = response.headers['x-quota-remaining'];
if (remaining < 5) {
console.warn('⚠️ Próximo do rate limit! Restam', remaining, 'requisições');
}
if (quotaRemaining < 100) {
console.warn('⚠️ Próximo da quota mensal! Restam', quotaRemaining);
}
}
Próximos Passos
- POST /render - Documentação completa da API
- Rate Limits - Entenda limites e otimização
- Webhooks - Processamento assíncrono
- Melhores Práticas - Otimizações avançadas