Troubleshooting
Esta página cataloga os problemas mais comuns encontrados ao desenvolver, testar ou operar o Neemias, com soluções passo a passo.
Se o problema não estiver listado aqui, verifique também o Quickstart, os ambientes de deploy e o README.
1. "Erro na inicialização" / "Cannot access storage"
Sintoma
Ao abrir o frontend, aparece uma mensagem de erro genérica de inicialização, ou o console do navegador mostra erros relacionados a IndexedDB, como DexieError, UnknownError, AbortError ou versionchange transaction.
Causa
O banco IndexedDB local (neemias-db) pode estar corrompido — comum durante desenvolvimento, após alterações no schema Dexie (db.ts) ou migrações que não aplicaram corretamente. O Dexie mantém conexões abertas e, em alguns cenários (recarregamento rápido, múltiplas abas), a transação de versionchange pode falhar.
O banco também pode ficar preso se outra aba do mesmo domínio estiver com uma conexão Dexie ativa.
Solução
- Abra o Chrome DevTools (F12).
- Vá para a aba Application → Storage → IndexedDB.
- Localize o banco
neemias-db. - Clique com botão direito → Delete database.
- Feche todas as outras abas do mesmo domínio (
localhost:5173ou o domínio de deploy) antes de recarregar. - Recarregue a página (F5).
Se o problema ocorrer em testes automatizados (Playwright/Puppeteer), navegue para about:blank antes de deletar — isso fecha a conexão Dexie ativa:
// Exemplo: limpeza de IndexedDB em testes Playwright
await page.goto("about:blank");
await page.evaluate(() => indexedDB.deleteDatabase("neemias-db"));
await page.goto("http://localhost:5173");Nota: Em ambiente de desenvolvimento, após limpar o IndexedDB o seed rodará novamente no próximo carregamento (se
DEPLOY_ENVnão forprod), repopulando 500 estudantes, 7 turmas e 20 núcleos.
2. Login falha com "Credenciais inválidas"
Sintoma
Ao tentar fazer login com admin@neemias.local / senha123 (ou outra credencial de seed), o backend retorna erro de credenciais inválidas.
Verificações
2a. O seed do backend foi executado?
O backend (Worker + D1) precisa ter o seed executado separadamente do frontend. O seed do frontend popula o IndexedDB; o seed do backend popula o D1.
# Verifique se as migrações foram aplicadas
pnpm db:migrate:local
# Execute o seed do backend
curl -X POST http://localhost:8788/api/v1/_seedRespostas esperadas:
200 OK— seed executado com sucesso.409 ConflictcomALREADY_SEEDED— o banco já contém usuários (ok).404 Not Found— o endpoint_seednão está disponível. Verifique se o Worker está rodando em modo desenvolvimento (wrangler dev).
2b. O DEPLOY_ENV está correto?
Se DEPLOY_ENV=prod, o seed é desabilitado — nem frontend nem backend população dados de demonstração. Verifique:
# No frontend: app/.env ou app/.env.local
# NÃO deve conter:
DEPLOY_ENV=prod
# Padrão seguro para dev:
# (deixe a variável ausente — o default é "dev")2c. Senha do seed foi alterada?
Se a variável SEED_PASSWORD estiver configurada no .dev.vars, a senha padrão senha123 não funcionará. Use a senha definida na variável, ou remova SEED_PASSWORD do .dev.vars e execute o seed novamente.
2d. Conferir usuários no D1
npx wrangler d1 execute neemias-db --local --command "SELECT email, role, status FROM users"Se a tabela estiver vazia, execute o seed.
Solução rápida (reset completo do ambiente dev)
# Remove o D1 local e recria
rm -rf .wrangler/state
pnpm db:migrate:local
curl -X POST http://localhost:8788/api/v1/_seed
# Limpa o IndexedDB do frontend (via DevTools) e recarrega3. Sincronização travada em "Sincronizando..."
Sintoma
A interface mostra "Sincronizando..." indefinidamente, ou os eventos criados offline nunca aparecem como sincronizados.
Verificações
3a. Backend está acessível?
O frontend precisa saber a URL do backend. Verifique o arquivo app/.env (ou .env.local):
# Deve conter:
VITE_BACKEND_URL=http://localhost:8788Se o arquivo não existir, crie-o:
echo 'VITE_BACKEND_URL=http://localhost:8788' > app/.envReinicie o frontend (pnpm dev) após criar ou alterar o .env.
3b. Worker está rodando?
# Terminal separado:
pnpm dev:worker
# ou:
cd workers && npx wrangler devO Worker deve responder em http://localhost:8788. Teste:
curl http://localhost:8788/api/v1/health3c. Token de acesso expirado?
Se o frontend estava logado há mais de 15 minutos e o Worker foi reiniciado (perdendo as sessões), o refresh pode falhar. Faça logout e login novamente.
3d. Modo sem backend (offline total)
Se você não precisa do backend e quer operar totalmente offline, use o botão "Marcar como sincronizado" nas Configurações (Settings). Isso força todos os eventos da fila de sincronização para o estado SYNCED sem comunicação com o backend, permitindo continuar operando normalmente.
Para desenvolver sem backend
Deixe VITE_BACKEND_URL vazio ou remova a variável do .env:
# app/.env.local
VITE_BACKEND_URL=Nesse modo, o frontend opera com autenticação local (sem validação de senha no backend) e todos os eventos são automaticamente marcados como sincronizados.
4. Erro "SENSITIVE_DATA_LOCKED"
Sintoma
No console do navegador, aparece o erro SENSITIVE_DATA_LOCKED ao tentar criar, editar ou excluir um estudante. A operação falha silenciosamente ou a interface mostra um estado inconsistente.
Causa
Os dados sensíveis (changePayload, justificativas) precisam ser criptografados com AES-GCM antes de serem salvos no IndexedDB, e a chave de criptografia é derivada da senha do usuário durante o login. Essa chave é mantida apenas em memória (Map<userId, KeyContext>).
O erro SENSITIVE_DATA_LOCKED significa que a chave para o usuário atual não está em memória. Isso acontece quando:
- A página foi recarregada (F5) e a sessão ainda não terminou de hidratar — o
AuthContextestá no meio do processo dehydrate(). - A sessão expirou (>15 min) e o refresh token falhou — o usuário foi desconectado.
- Houve uma condição de corrida: a operação de escrita foi disparada antes do
unlockSensitiveData()completar.
Existe também um edge case conhecido em que a hidratação da sessão (hydrate()) compete com a renderização inicial da página, causando uma janela onde o AuthContext.isAuthenticated é true mas o KeyContext ainda não foi populado. Este problema está documentado na lesson L-002 do STATE.md.
Solução
- Faça logout e login novamente. Isso força uma nova derivação de chave e recria o
KeyContextdo zero. - Aguarde a interface carregar completamente antes de interagir — o indicador de loading deve desaparecer.
- Se o problema persistir, limpe o IndexedDB (ver Problema 1) e faça login novamente.
5. Google Maps Autocomplete não carrega
Sintoma
O campo de endereço não mostra sugestões do Google Maps. O console exibe erro Google Maps JavaScript API error: RefererNotAllowedMapError ou similar.
Verificações
5a. Chave da API configurada?
# app/.env.local deve conter:
VITE_GOOGLE_MAPS_API_KEY=sua_chave_aquiA chave é carregada em app/src/lib/googleMaps.ts via import.meta.env.VITE_GOOGLE_MAPS_API_KEY. Sem ela, o script do Google Maps não é carregado e o autocomplete simplesmente não aparece (falha silenciosa).
5b. Restrições de HTTP referrer
No Google Cloud Console, verifique as restrições da chave:
- Para desenvolvimento local, adicione
localhostelocalhost:5173(ou a porta que estiver usando) à lista de referrers permitidos. - Para staging/produção, adicione o domínio do Cloudflare Pages (ex:
neemias.app,staging.neemias.app).
Formato no campo "HTTP referrers":
localhost
*.localhost
localhost:*
neemias.app
*.neemias.app5c. APIs habilitadas?
No Google Cloud Console, verifique se as seguintes APIs estão ativadas para o projeto:
- Places API
- Maps JavaScript API
6. Build falha com "Cannot find module"
Sintoma
Ao rodar pnpm build:app ou pnpm build:worker, o build falha com erro de módulo não encontrado:
Error: Cannot find module '@neemias/schemas'
Error: Cannot find module 'jose'Causa
As dependências do monorepo não estão instaladas ou o node_modules está em um estado inconsistente. O projeto usa pnpm workspaces — as dependências são vinculadas via node_modules/.pnpm e symlinks.
Solução
# Da raiz do monorepo:
pnpm installSe o problema persistir, faça uma limpeza completa:
# Remove node_modules e lockfile
rm -rf node_modules packages/*/node_modules app/node_modules workers/node_modules
rm -rf pnpm-lock.yaml
# Reinstala do zero
pnpm install
pnpm -r buildVerifique também que você está usando a versão correta do pnpm (>=8.x):
pnpm --version
corepack enable # se estiver usando corepack7. Deploy do Worker falha
Sintoma
npx wrangler deploy ou ./scripts/deploy.sh falha com erro de autenticação:
Error: Failed to get account ID. Please provide an account_id in your wrangler.toml
Error: Authentication error: Unable to verify accountVerificações
7a. Token da Cloudflare configurado?
O Wrangler precisa de autenticação. Verifique se você está logado:
npx wrangler whoamiSe não estiver logado:
npx wrangler login7b. CLOUDFLARE_API_TOKEN configurado (CI/CD)?
Em ambientes de CI (GitHub Actions), configure o token como variável de ambiente ou secret:
# Local (.dev.vars — apenas para teste, não commitar):
CLOUDFLARE_API_TOKEN=seu_token_aqui
# CI: configurar como secret no GitHub Actions
# Settings → Secrets and variables → Actions → CLOUDFLARE_API_TOKENPara criar um token: Cloudflare Dashboard → Create Token → Use o template "Edit Cloudflare Workers".
7c. account_id no wrangler.toml?
Verifique se o wrangler.toml contém o account_id correto (ou se está sendo inferido pelo token):
# workers/wrangler.toml
name = "neemias"
main = "src/index.ts"
compatibility_date = "2025-06-01"
# Opcional se o token tiver acesso:
# account_id = "seu_account_id"7d. Migrações D1 antes do deploy?
Se o Worker foi modificado e requer novas migrações:
# Aplicar migrações no ambiente remoto
npx wrangler d1 execute neemias-db --remote --file=migrations/0001_init.sql
npx wrangler d1 execute neemias-db --remote --file=migrations/0002_auth_sessions.sql
# ... etc.8. D1 retorna "D1_ERROR: no such table"
Sintoma
O Worker responde com erro 500 e no log aparece:
D1_ERROR: no such table: studentsCausa
As migrações D1 não foram aplicadas no banco local ou remoto. O arquivo .wrangler/state pode estar corrompido ou ter sido removido sem reaplicar as migrações.
Solução
Ambiente local:
# Aplica todas as migrações no D1 local
pnpm db:migrate:local
# Executa o seed
curl -X POST http://localhost:8788/api/v1/_seedAmbiente remoto (produção/staging):
# Lista migrações pendentes
npx wrangler d1 migrations list neemias-db --remote
# Aplica migrações
npx wrangler d1 migrations apply neemias-db --remoteCuidado: nunca execute migrações
--remoteem produção sem antes testar localmente.
9. Testes falham com crypto.subtle indisponível
Sintoma
Ao rodar pnpm test, testes que envolvem encryptionService ou password.ts falham com:
ReferenceError: crypto is not defined
TypeError: crypto.subtle is undefinedCausa
Os testes usam o Vitest com ambiente node por padrão, mas o crypto.subtle (Web Crypto API) não está disponível no Node.js sem flags experimentais ou polyfills. Os testes do frontend mockam encryptionService (vi.mock), mas se um teste não aplicar o mock, encontrará o crypto.subtle real, que não existe.
Solução
Certifique-se de que todos os módulos que importam a encryptionService nos arquivos de teste tenham o mock aplicado antes do import:
// Correto — mock antes do import
vi.mock("../auth/encryptionService", () => ({
encryptSensitiveValue: vi.fn(async () => ({ ciphertext: "x", iv: "y", keyVersion: 1 })),
decryptSensitiveValue: vi.fn(),
sha256: vi.fn(async (input: string) => input + "-hashed"),
}));
import { minhaFuncao } from "../meuModulo";Os testes do Worker (workers/src/__tests__/) rodam em ambiente workerd via vitest-environment-miniflare, que tem crypto.subtle disponível — não precisam de mock para criptografia.
10. Página em branco após deploy no Cloudflare Pages
Sintoma
Após deploy no Cloudflare Pages, a página carrega completamente em branco (sem erros visíveis, ou com erro MIME type no console).
Causas possíveis
- SPA routing: o Cloudflare Pages não está configurado para servir o
index.htmlem todas as rotas. O Neemias usa React Router — todas as requisições precisam cair noindex.html. - Build incompleto: o
pnpm build:appnão gerou todos os arquivos emapp/dist/. - DEPLOY_ENV incorreto: o build foi feito com
DEPLOY_ENVvazio ou incorreto, e o seed tentou rodar em produção.
Solução
Roteamento SPA:
Adicione um arquivo _routes.json no diretório app/dist/ (ou configure no dashboard do Cloudflare Pages) para redirecionar todas as rotas para index.html:
{
"version": 1,
"include": ["/*"],
"exclude": ["/assets/*", "/favicon.ico"]
}Verificar o build:
pnpm build:app
ls app/dist/ # Deve listar index.html, assets/, etc.Verificar DEPLOY_ENV:
# No Cloudflare Pages Dashboard:
# Settings → Environment variables → Production
# DEPLOY_ENV = prod
# Ou via CLI:
wrangler pages secret put DEPLOY_ENV --project-name neemias-prod
# (digitar: prod)Referência rápida
| Problema | Causa mais comum | Ação imediata |
|---|---|---|
| Erro na inicialização | IndexedDB corrompido | Deletar neemias-db no DevTools |
| Credenciais inválidas | Seed não executado no backend | curl -X POST localhost:8788/api/v1/_seed |
| Sincronizando... | VITE_BACKEND_URL ausente/errado | Verificar app/.env |
| SENSITIVE_DATA_LOCKED | Sessão expirada | Logout → Login |
| Google Maps não carrega | Chave API ou referrer | Verificar .env.local e Cloud Console |
| Cannot find module | pnpm install pendente | pnpm install da raiz |
| Worker deploy falha | Autenticação Wrangler | wrangler whoami / wrangler login |
| D1_ERROR: no such table | Migrações não aplicadas | pnpm db:migrate:local |
| Página em branco (Pages) | SPA routing ou build | Verificar _routes.json e DEPLOY_ENV |
Ainda não resolveu?
- Consulte os logs do Worker no dashboard da Cloudflare.
- Verifique o console do navegador (F12) para erros detalhados.
- Leia o STATE.md para problemas conhecidos e lessons learned.
- Abra uma issue no GitHub com:
- Descrição do problema
- Passos para reproduzir
- Logs do console e do terminal
- Ambiente (
dev/staging/prod, com ou sem backend)