Skip to content

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

  1. Abra o Chrome DevTools (F12).
  2. Vá para a aba ApplicationStorageIndexedDB.
  3. Localize o banco neemias-db.
  4. Clique com botão direito → Delete database.
  5. Feche todas as outras abas do mesmo domínio (localhost:5173 ou o domínio de deploy) antes de recarregar.
  6. 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:

js
// 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_ENV não for prod), 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.

bash
# Verifique se as migrações foram aplicadas
pnpm db:migrate:local

# Execute o seed do backend
curl -X POST http://localhost:8788/api/v1/_seed

Respostas esperadas:

  • 200 OK — seed executado com sucesso.
  • 409 Conflict com ALREADY_SEEDED — o banco já contém usuários (ok).
  • 404 Not Found — o endpoint _seed nã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:

bash
# 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

bash
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)

bash
# 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 recarrega

3. 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):

bash
# Deve conter:
VITE_BACKEND_URL=http://localhost:8788

Se o arquivo não existir, crie-o:

bash
echo 'VITE_BACKEND_URL=http://localhost:8788' > app/.env

Reinicie o frontend (pnpm dev) após criar ou alterar o .env.

3b. Worker está rodando?

bash
# Terminal separado:
pnpm dev:worker
# ou:
cd workers && npx wrangler dev

O Worker deve responder em http://localhost:8788. Teste:

bash
curl http://localhost:8788/api/v1/health

3c. 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:

bash
# 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:

  1. A página foi recarregada (F5) e a sessão ainda não terminou de hidratar — o AuthContext está no meio do processo de hydrate().
  2. A sessão expirou (>15 min) e o refresh token falhou — o usuário foi desconectado.
  3. 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

  1. Faça logout e login novamente. Isso força uma nova derivação de chave e recria o KeyContext do zero.
  2. Aguarde a interface carregar completamente antes de interagir — o indicador de loading deve desaparecer.
  3. 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?

bash
# app/.env.local deve conter:
VITE_GOOGLE_MAPS_API_KEY=sua_chave_aqui

A 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 localhost e localhost: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.app

5c. 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

bash
# Da raiz do monorepo:
pnpm install

Se o problema persistir, faça uma limpeza completa:

bash
# 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 build

Verifique também que você está usando a versão correta do pnpm (>=8.x):

bash
pnpm --version
corepack enable  # se estiver usando corepack

7. 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 account

Verificações

7a. Token da Cloudflare configurado?

O Wrangler precisa de autenticação. Verifique se você está logado:

bash
npx wrangler whoami

Se não estiver logado:

bash
npx wrangler login

7b. CLOUDFLARE_API_TOKEN configurado (CI/CD)?

Em ambientes de CI (GitHub Actions), configure o token como variável de ambiente ou secret:

bash
# 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_TOKEN

Para 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):

toml
# 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:

bash
# 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: students

Causa

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:

bash
# Aplica todas as migrações no D1 local
pnpm db:migrate:local

# Executa o seed
curl -X POST http://localhost:8788/api/v1/_seed

Ambiente remoto (produção/staging):

bash
# Lista migrações pendentes
npx wrangler d1 migrations list neemias-db --remote

# Aplica migrações
npx wrangler d1 migrations apply neemias-db --remote

Cuidado: nunca execute migrações --remote em 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 undefined

Causa

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:

ts
// 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

  1. SPA routing: o Cloudflare Pages não está configurado para servir o index.html em todas as rotas. O Neemias usa React Router — todas as requisições precisam cair no index.html.
  2. Build incompleto: o pnpm build:app não gerou todos os arquivos em app/dist/.
  3. DEPLOY_ENV incorreto: o build foi feito com DEPLOY_ENV vazio 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:

json
{
  "version": 1,
  "include": ["/*"],
  "exclude": ["/assets/*", "/favicon.ico"]
}

Verificar o build:

bash
pnpm build:app
ls app/dist/                    # Deve listar index.html, assets/, etc.

Verificar DEPLOY_ENV:

bash
# 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

ProblemaCausa mais comumAção imediata
Erro na inicializaçãoIndexedDB corrompidoDeletar neemias-db no DevTools
Credenciais inválidasSeed não executado no backendcurl -X POST localhost:8788/api/v1/_seed
Sincronizando...VITE_BACKEND_URL ausente/erradoVerificar app/.env
SENSITIVE_DATA_LOCKEDSessão expiradaLogout → Login
Google Maps não carregaChave API ou referrerVerificar .env.local e Cloud Console
Cannot find modulepnpm install pendentepnpm install da raiz
Worker deploy falhaAutenticação Wranglerwrangler whoami / wrangler login
D1_ERROR: no such tableMigrações não aplicadaspnpm db:migrate:local
Página em branco (Pages)SPA routing ou buildVerificar _routes.json e DEPLOY_ENV

Ainda não resolveu?

  1. Consulte os logs do Worker no dashboard da Cloudflare.
  2. Verifique o console do navegador (F12) para erros detalhados.
  3. Leia o STATE.md para problemas conhecidos e lessons learned.
  4. 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)

Distribuído sob licença MIT.