Troubleshooting — Cobranca-API
Versão: 1.5.0
Este guia ajuda a resolver problemas comuns ao usar a API.
Índice
- Logging
- Deploy no Render.com
- Erros Comuns — Boletos
- Erros Comuns — Remessa CNAB
- Erros Comuns — Retorno CNAB
- Erros Comuns — OFX
- Checklist de Debug
Logging
A API produz logs estruturados em JSON via RequestLogger middleware:
{"event":"request_start","method":"POST","path":"/api/ofx/parse","timestamp":"2026-04-09T12:00:00.000+0000"}
{"event":"request_end","method":"POST","path":"/api/ofx/parse","status":201,"duration_ms":4.69,"timestamp":"..."}
Erros são logados via ErrorHandler:
2026-04-09T12:00:00.000+0000 [ERROR] [400] ValidationError: Parâmetro inválido - file is missing
Deploy no Render.com
Logs não aparecem no dashboard do Render
Causa: em container, o Python bufferiza stdout/stderr em blocos. Os
logs só aparecem quando o buffer enche — o que em baixo volume pode demorar
muito ou nunca acontecer.
Solução (já aplicada): o Dockerfile define PYTHONUNBUFFERED=1, que
desliga o buffer do interpretador. O uvicorn escreve direto no stdout do
container.
Verificação local:
docker run --rm cobranca-api python -c "import sys; print(sys.stdout.line_buffering)"
docker logs -f <container> # deve sair linha a linha
Se ainda assim não aparecer:
- Confirme
PYTHONUNBUFFERED=1(docker inspect→Config.Env) - Force rebuild no Render (Manual Deploy → Clear build cache & deploy)
- No dashboard, clique em “Logs” e role para cima (Render mostra as últimas 1000 linhas)
HTTP 429 — Too Many Requests (cold start)
Causa: Isto não é rate limiting da API — a API não possui rate limiting. O 429 vem do próprio Render.com free tier:
- Cold start (sleep mode): Após 15 minutos de inatividade, o Render suspende o serviço. A primeira request pode demorar 30-60s para acordar.
- Durante o wake up, requests subsequentes podem receber 429 ou 503 enquanto o serviço se inicializa.
- Se o cliente envia múltiplas requests em paralelo ou em sequência rápida, as primeiras acordam o serviço e as seguintes podem receber 429 enquanto o wake está em progresso.
Exemplo no log do cliente:
ERROR ... Erro Cobranca-API: 429 - Too Many Requests
ERROR ... Erro Cobranca-API: 429 - Too Many Requests (480ms depois)
Soluções:
| Opção | Custo | Descrição |
|---|---|---|
| 1. Retry com backoff no cliente | Grátis | Implementar retry exponencial (1s, 2s, 4s, 8s) até 4 tentativas |
| 2. Ping service (manter acordado) | Grátis | Usar cron-job.org ou UptimeRobot para pingar /api/health a cada 10 minutos (14 min fica no limite do sleep de 15 min). Há também o workflow .github/workflows/keepalive.yml |
| 3. Upgrade para Starter ($7/mês) | Pago | Elimina sleep mode e aumenta RAM para 2GB |
Exemplo de retry em Python (no cliente):
import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retry = Retry(
total=4,
backoff_factor=1, # 1s, 2s, 4s, 8s
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=['GET', 'POST']
)
session.mount('https://', HTTPAdapter(max_retries=retry))
# Primeira chamada acorda o servidor
response = session.get('https://SEU-SERVICO.onrender.com/api/health', timeout=60)
Exemplo de ping service (cron-job.org):
- URL:
https://SEU-SERVICO.onrender.com/api/health - Intervalo: a cada 10 minutos
- Método: GET
- Timeout: 30s
Erros Comuns — Boletos
1. type is missing
Causa: Endpoint /api/boleto (GET) requer 3 parâmetros obrigatórios:
bank— Nome do banco (banco_brasil,sicoob, etc)type— Formato de saída (pdf,jpg,png,tif)data— JSON com os dados do boleto
Response (400):
{"error": "Parâmetro inválido", "details": "type is missing", "type": "ValidationError"}
Solução:
response = requests.get(
f"{API_URL}/api/boleto",
params={
"bank": "sicoob",
"type": "pdf",
"data": json.dumps(boleto_data)
}
)
2. JSON inválido
Response (400):
{"error": "JSON inválido", "details": "unexpected token at '{'", "type": "JSON::ParserError"}
Solução: Use aspas duplas no JSON. Em Python, use json.dumps().
3. Campos obrigatórios ausentes
Response (400):
{
"error": "Dados do boleto inválidos",
"validation_errors": {
"nosso_numero": ["não pode ficar em branco"],
"agencia": ["não é um número"]
},
"hint": "Verifique se todos os campos obrigatórios estão preenchidos"
}
Solução: Use /api/boleto/validate antes de gerar o PDF. Veja fields/all-banks.md para campos obrigatórios por banco.
4. numero_documento vs documento_numero
nosso_numero— Obrigatório, faz parte do código de barrasnumero_documento— Nome usado pela API (controle interno da empresa)documento_numero— Nome interno da engine (não usar diretamente na API)
A API converte numero_documento → documento_numero automaticamente.
# ✅ Correto
boleto_data = {
"numero_documento": "NF-12345",
"nosso_numero": "1234567",
}
5. Linha digitável vazia
Causa: Falta nosso_numero ou outros campos obrigatórios.
Debug:
# Validar antes de gerar
validate = requests.get(
f"{API_URL}/api/boleto/validate",
params={"bank": "sicoob", "data": json.dumps(boleto_data)}
)
print(validate.json())
6. aceite / especie_documento em branco
Comportamento: campos com valor padrão (aceite, especie_documento,
especie, moeda, local_pagamento) enviados em branco ("") caem
automaticamente no default do brcobrança (aceite='S', especie_documento='DM',
especie='R$', moeda='9'). Não é mais necessário omitir o campo — vazio e
ausente têm o mesmo efeito. Para usar outro valor, basta enviá-lo preenchido.
Erros Comuns — Remessa CNAB
1. Formato CNAB incorreto
Response (400):
{"error": "Erro ao gerar remessa", "validation_errors": ["Formato '240' não suportado. Use: cnab240, cnab400"]}
Solução: Use cnab240 ou cnab400 (não apenas 240 ou 400) no parâmetro type.
2. Pagamentos devem ser objetos
Causa: Envio de array vazio ou com formato incorreto.
Solução: Cada pagamento no array deve conter:
{
"nosso_numero": "123456789",
"data_vencimento": "2025/12/31",
"valor": 1500.00,
"sacado": "João da Silva",
"sacado_documento": "12345678900"
}
3. Campos obrigatórios no cabeçalho da remessa
Alguns bancos exigem campos específicos:
| Banco | Campo obrigatório |
|---|---|
| Sicoob (CNAB 240) | convenio, modalidade (o variacao é do boleto e é ignorado na remessa) |
| Banco do Brasil | convenio (4-7 dígitos) |
| Itaú | carteira |
Consulte fields/all-banks.md.
4. Remessa PIX — banco não suportado
Response (400):
{"error": "Parâmetro inválido", "details": "Remessa PIX não disponível para banco 'banrisul' com formato 'cnab400'."}
Solução: Verifique a tabela de suporte PIX em api/pix.md. Nem todo banco suporta PIX em todos os formatos CNAB.
5. Sicoob Layout 810
Para usar o layout alternativo onde o cliente calcula o DV, envie no payload da remessa Sicoob CNAB240:
{"versao_layout_arquivo_opcao": "810", ...}
O valor padrão é "081". O campo passa direto para a gem sem necessidade de configuração adicional na API.
6. Campos não suportados pela classe de remessa são ignorados
Comportamento: um campo que existe no boleto mas não na classe de
remessa do banco é ignorado (não gera erro). Exemplo: variacao é usado no
boleto Sicoob, mas não existe na remessa CNAB 240 do Sicoob — enviar variacao
no payload CNAB 240 não quebra a geração. O mesmo vale para campos extras dentro
de cada pagamento (ex.: cedente vazado do nível de remessa): são descartados
em vez de causar 500. Campos obrigatórios ausentes continuam retornando erro
de validação normalmente.
Erros Comuns — Retorno CNAB
1. Banco ou tipo não encontrado
Response (400):
{"error": "Banco ou tipo não encontrado", "details": "Classe de retorno não encontrada para banco 'xyz' e tipo 'cnab400'"}
Solução: Verifique se o banco suporta o tipo CNAB em fields/all-banks.md.
2. Arquivo vazio ou corrompido
Debug: Verifique tamanho do arquivo e primeiras linhas:
wc -l retorno.ret
head -3 retorno.ret
Arquivos CNAB 400 têm linhas de 400 caracteres; CNAB 240 tem 240 caracteres.
Erros Comuns — OFX
1. Arquivo OFX inválido
Response (400):
{"erro": "Arquivo OFX inválido ou não reconhecido: <detalhes>"}
Causa: Arquivo não é um OFX válido ou está corrompido.
Solução:
- Confirme que é um arquivo
.ofx(não.retque é CNAB de retorno) - Abra em um editor e verifique se começa com
OFXHEADER:(v1) ou<?xml(v2) - Tente abrir em um visualizador OFX (Money, GnuCash, etc)
2. file is missing
Response (400):
{"error": "Parâmetro inválido", "details": "file is missing", "type": "ValidationError"}
Causa: Campo file não enviado ou nome errado.
Solução:
# ✅ Correto
curl -X POST http://localhost:8000/api/ofx/parse -F "file=@extrato.ofx"
# ❌ Errado (campo errado)
curl -X POST http://localhost:8000/api/ofx/parse -F "data=@extrato.ofx"
3. nosso_numero sempre null
Causa: Banco não reconhecido ou memo sem sequência numérica adequada.
Debug:
response = requests.post(
f"{API_URL}/api/ofx/parse",
files={'file': open('extrato.ofx', 'rb')}
)
data = response.json()
# Confirme que o banco foi reconhecido
print(f"Banco: {data['banco']}") # {'org': 'SICOOB', 'fid': '756'}
# Veja os memos
for tx in data['transacoes']:
print(f"memo: '{tx['memo']}' → {tx['nosso_numero']}")
Veja ofx-parsing.md para os padrões regex de cada banco.
4. Caracteres com encoding errado (�, ?)
Causa: Arquivo original tem encoding diferente de Latin-1 ou UTF-8.
O service tenta automaticamente:
- UTF-8 (se válido)
- Latin-1 → UTF-8 (padrão de bancos brasileiros)
- ASCII-8BIT com replace (fallback)
Se ainda assim houver problemas, reporte um issue com arquivo de exemplo.
Checklist de Debug
Boleto não gera
- Todos os 3 parâmetros (
bank,type,data) estão sendo enviados? - JSON é válido (use
json.dumps())? - Usou
/api/boleto/validateprimeiro? - Campo
nosso_numeroestá presente? data_vencimentoestá no formatoYYYY/MM/DD?- Consultou os campos obrigatórios em fields/all-banks.md?
Remessa não gera
typeécnab240oucnab400(não apenas números)?- Array
pagamentostem pelo menos 1 item? - Cada pagamento tem
nosso_numero,data_vencimento,valor,sacado,sacado_documento? - Banco suporta o tipo CNAB? (Bradesco não suporta CNAB240)
OFX não parseia
- Arquivo é
.ofxválido (v1 SGML ou v2 XML)? - Enviou via
multipart/form-datacom campofile? - Verificou que o banco foi reconhecido (
banco.orgno response)? - Confirmou encoding do arquivo?
Suporte
- Documentação: documentação do projeto
- Campos por banco: docs/fields/all-banks.md
- OpenAPI Spec: docs/openapi.yaml
- Issues: https://github.com/Maxwbh/cobranca-api/issues
Mantido por: Maxwell da Silva Oliveira (@maxwbh) - M&S do Brasil LTDA