🩺 GUIA DE TROUBLESHOOTING E FAQ DE ENGENHARIA
Durante o desenvolvimento de software e persistência de dados, encontrar erros e exceções no terminal faz parte natural da jornada de aprendizado.
Este guia reúne os erros mais comuns enfrentados pelos estudantes, explicando a causa raiz, o que a mensagem técnica significa e o passo a passo exato para resolver o problema em segundos. 🛡️⚡
🧭 Índice Rápido de Diagnóstico
flowchart TD
E["🚨 Encontrou um Erro?"] --> API["🌐 1. Erros de API, Flask & Pydantic (400, 404, 405, Porta 5000)"]
E --> ORM["🛢️ 2. Erros de Banco & SQLAlchemy (IntegrityError, Lock)"]
E --> ENV["🐳 3. Erros de Docker, Portas & Venv (Porta 5432 Ocupada)"]
E --> MIG["🔄 4. Erros de Alembic & Migrations (Multiple Heads)"]
E --> JINJA["🎨 5. Erros de Template Jinja2 (TemplateNotFound)"]
style E fill:#fee2e2,stroke:#ef4444
style API fill:#e0f2fe,stroke:#0284c7
style ORM fill:#fef3c7,stroke:#d97706
style ENV fill:#dcfce7,stroke:#16a34a
style MIG fill:#f3e8ff,stroke:#9333ea
style JINJA fill:#fce7f3,stroke:#db2777
🌐 1. Erros de API, Flask 3.x e Pydantic
❌ Erro 1.1: Porta 5000 já em uso (OSError: [WinError 10048])
- Sintoma: Ao executar
python -m app.main, o terminal exibeOSError: [WinError 10048] Only one usage of each socket address is normally permitted. - Causa Raiz: Uma instância anterior do servidor Flask ainda está rodando em segundo plano no Windows e segurando a porta 5000.
- Como Resolver: Abra o PowerShell e encerre os processos Python ativos:
Get-Process python* | Stop-Process -Force
❌ Erro 1.2: 400 Bad Request ao validar payload com Pydantic
- Sintoma: Ao enviar uma requisição
POSTouPUT, a API retorna400 Bad Requestcom o detalhe do erro do Pydantic ourequest.get_json()retornaNone. - Causa Raiz: O cliente não enviou o cabeçalho
Content-Type: application/jsonou faltou algum campo obrigatório exigido pelo Schema. - Como Resolver:
- No PowerShell com
Invoke-RestMethod, garanta o parâmetro-ContentType "application/json". - Verifique se o JSON contém todas as chaves exigidas pelo schema Pydantic.
- No handler do Flask, utilize sempre tratamento com bloco
try/except:
- No PowerShell com
dados = request.get_json() or {}
try:
payload = MeuSchema(**dados)
except Exception as err:
return jsonify({"detail": str(err)}), 400
❌ Erro 1.3: 405 Method Not Allowed
- Sintoma: Ao submeter um formulário ou chamar um endpoint, o navegador exibe
405 Method Not Allowed. - Causa Raiz: O endpoint foi registrado para um verbo HTTP (ex:
@app.get("/usuarios")), mas a requisição foi feita usando outro método (ex:POST). - Como Resolver:
- No formulário HTML, confira a tag:
<form action="/usuarios" method="POST">. - No arquivo do router Flask, certifique-se de que o método HTTP coincide:
- No formulário HTML, confira a tag:
@router.route("/usuarios", methods=["POST"])
# ou:
@router.post("/usuarios")
❌ Erro 1.4: Erro de CORS (Blocked by CORS Policy)
- Sintoma: O frontend não consegue se comunicar com a API e o console do navegador exibe:
Access to XMLHttpRequest at 'http://localhost:5000/api' has been blocked by CORS policy. - Causa Raiz: Por segurança, navegadores bloqueiam requisições JavaScript vindas de origens/portas diferentes.
- Como Resolver: Adicione os headers CORS ou utilize
flask-cors:
@app.after_request
def add_cors_headers(response):
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Headers"] = "Content-Type,Authorization"
response.headers["Access-Control-Allow-Methods"] = "GET,POST,PUT,DELETE,OPTIONS"
return response
🛢️ 2. Erros de Banco de Dados & SQLAlchemy 2.0
❌ Erro 2.1: sqlalchemy.exc.IntegrityError: NOT NULL constraint failed
- Sintoma: Falha ao tentar salvar um registro com
session.commit(). - Causa Raiz: O modelo possui uma coluna com
nullable=False(ouMapped[str]sem| None), mas o objeto foi instanciado sem preencher esse valor. - Como Resolver: Garanta que todos os campos obrigatórios sejam passados no construtor do modelo antes de executar
session.add():
# ❌ Incorreto:
novo_cliente = Cliente(email="carlos@email.com") # Faltou o nome!
# ✅ Correto:
novo_cliente = Cliente(nome="Carlos Silva", email="carlos@email.com")
❌ Erro 2.2: sqlite3.OperationalError: database is locked
- Sintoma: O SQLite trava e emite erro informando que o arquivo de banco de dados está bloqueado.
- Causa Raiz: Uma sessão anterior abriu uma transação de escrita e não foi encerrada com
session.commit(),session.rollback()ousession.close(), ou o banco está aberto para edição concorrente em outra ferramenta (como DB Browser). - Como Resolver:
- Garanta que a função
get_db()utilizeyieldefinally: db.close(). - Feche conexões manuais abertas em ferramentas externas.
- No
database.py, configure timeout para o SQLite:
- Garanta que a função
engine = create_engine(
"sqlite:///dev.db",
connect_args={"timeout": 30} # Aguarda até 30s antes de falhar
)
❌ Erro 2.3: sqlalchemy.orm.exc.DetachedInstanceError
- Sintoma: Erro ao acessar um relacionamento (ex:
usuario.pedidos) no template Jinja2 ou após sair da função de rota. - Causa Raiz: O SQLAlchemy usa carregamento preguiçoso (Lazy Loading) por padrão. Quando a sessão do banco foi fechada pelo
get_db(), o objeto perdeu a conexão ativa necessária para buscar os dados filhos. - Como Resolver: Utilize
joinedload()ouselectinload()na consulta para trazer os relacionamentos de forma ansiosa (Eager Loading):
from sqlalchemy.orm import selectinload
stmt = select(Usuario).options(selectinload(Usuario.pedidos)).where(Usuario.id == 1)
usuario = session.scalars(stmt).first()
🐳 3. Erros de Docker, Portas e Ambiente Virtual
❌ Erro 3.1: Bind for 0.0.0.0:5432 failed: port is already allocated
- Sintoma: Ao rodar
docker compose up -d, o terminal acusa que a porta 5432 já está em uso. - Causa Raiz: O serviço do PostgreSQL nativo do Windows já está rodando em segundo plano e ocupando a porta 5432 da máquina física.
- Como Resolver (Opção A — Parar o serviço do Windows):
- Abra o PowerShell como Administrador e execute:
Stop-Service postgresql*
- Como Resolver (Opção B — Mudar a porta no
docker-compose.yml):- Mude o mapeamento para usar a porta 5433 no seu computador:
ports:
- "5433:5432" # 5433 no Windows -> 5432 dentro do container
- Atualize seu
.env:DATABASE_URL=postgresql://postgres:senha@localhost:5433/meu_db.
❌ Erro 3.2: Erro de Permissão ao Ativar o Venv no PowerShell (Script Execution Policy)
- Sintoma: Ao rodar
.\venv\Scripts\Activate.ps1, o PowerShell exibe:não pode ser carregado porque a execução de scripts foi desabilitada neste sistema. - Causa Raiz: Política de segurança padrão do Windows para scripts locais.
- Como Resolver: Abra o PowerShell e libere para o seu usuário atual:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
🔄 4. Erros de Migrações com Alembic
❌ Erro 4.1: alembic.util.exc.CommandError: Target database is not up to date
- Sintoma: Erro ao tentar rodar
alembic revision --autogenerate. - Causa Raiz: Existem migrações anteriores no histórico que ainda não foram aplicadas no banco de dados atual.
- Como Resolver: Aplique todas as migrações pendentes antes de gerar uma nova:
alembic upgrade head
alembic revision --autogenerate -m "nova_alteracao"
alembic upgrade head
❌ Erro 4.2: Conflito de Versões (Multiple head revisions are present)
- Sintoma: Conflito após fazer
git pullde alterações de outro colega de grupo no Projeto Integrador. - Causa Raiz: Dois alunos criaram migrações simultaneamente em branches separadas.
- Como Resolver: Crie uma migração de merge para unir as duas pontas:
alembic merge heads -m "merge_conflitos"
alembic upgrade head
🎨 5. Erros de Template e Renderização Jinja2
❌ Erro 5.1: jinja2.exceptions.TemplateNotFound: index.html
- Sintoma: A aplicação Flask falha com erro de template não encontrado ao tentar renderizar a view.
- Causa Raiz: O caminho informado no
template_folderdo Flask está incorreto ou a pastatemplatesnão está no mesmo nível do diretórioapp/. - Como Resolver: Configure o caminho absoluto baseado na raiz do diretório
app/:
from pathlib import Path
from flask import Flask, render_template
BASE_DIR = Path(__file__).resolve().parent
app = Flask(__name__, template_folder=str(BASE_DIR / "templates"))
❌ Erro 5.2: jinja2.exceptions.UndefinedError: 'item' is undefined
- Sintoma: A página quebra durante a renderização no navegador.
- Causa Raiz: O template
.htmltenta acessar uma variável{{ item.nome }}, mas ela não foi passada nos argumentos dorender_template(...). - Como Resolver: Verifique a rota no
main.pye certifique-se de passar o objeto nomeado no retorno:
@app.route("/detalhes/<int:id>")
def detalhes(id: int):
item_do_banco = ...
return render_template("detalhes.html", item=item_do_banco)