Solução de problemas

Falha na conexão com o banco de dados

# Check database is running
docker compose ps db

# Test connection
docker compose exec db psql -U postgres -c "SELECT 1"

Confira o formato de DATABASE_URL: postgresql://user:pass@host:5432/database

Modelos do Ollama não aparecem

Dentro do Docker, localhost = o container, não a sua máquina host.

# For host-machine Ollama, use:
OLLAMA_URL=http://host.docker.internal:11434  # macOS/Windows
OLLAMA_URL=http://192.168.1.x:11434           # Linux (use actual IP)

WebSocket/realtime não funciona

  1. Confirme que o proxy reverso roteia /socket.io para o serviço de realtime (porta padrão 3002). NEXT_PUBLIC_SOCKET_URL só é necessário se o realtime estiver em outro host.
  2. Confirme que o serviço de realtime está rodando: docker compose ps realtime
  3. Garanta que o proxy reverso repassa os upgrades de WebSocket (veja o guia do Docker)

502 Bad Gateway

# Check app is running
docker compose ps studio
docker compose logs studio

# Common causes: out of memory, database not ready

Erros de migration

As migrations rodam no próprio serviço e imagem migrations — a imagem do app não contém as ferramentas de migration.

# View migration logs
docker compose -f docker-compose.prod.yml logs migrations

# Re-run them
docker compose -f docker-compose.prod.yml up --force-recreate migrations

No Kubernetes, as migrations são um init container no pod do app:

kubectl logs -n studio deploy/studio-app -c migrations --tail=200

pgvector não encontrado

Use a imagem correta do PostgreSQL:

image: pgvector/pgvector:pg17 # NOT postgres:17

Erros de certificado (CERT_HAS_EXPIRED)

Se você vê erros de certificado SSL ao chamar APIs externas:

A imagem já vem com certificados de CA atualizados e roda com um usuário não-root, então instalar pacotes dentro dela não é a solução. Isso quase sempre significa que o endpoint apresenta um certificado assinado por uma CA privada — um proxy corporativo que inspeciona TLS, ou um serviço interno.

Monte o seu bundle de CA e aponte o Node para ele:

# docker-compose.prod.yml
services:
  studio:
    volumes:
      - /etc/ssl/certs/corporate-ca.crt:/certs/corporate-ca.crt:ro
    environment:
      - NODE_EXTRA_CA_CERTS=/certs/corporate-ca.crt
# Helm — mount a ConfigMap holding the CA
app:
  env:
    NODE_EXTRA_CA_CERTS: /certs/corporate-ca.crt
  extraVolumes:
    - name: corporate-ca
      configMap:
        name: corporate-ca
  extraVolumeMounts:
    - name: corporate-ca
      mountPath: /certs
      readOnly: true

NODE_TLS_REJECT_UNAUTHORIZED=0 desativa a verificação de certificados por completo e nunca deve ser usado fora de um teste descartável.

Página em branco após o login

  1. Verifique erros no console do navegador
  2. Confirme que NEXT_PUBLIC_APP_URL corresponde ao seu domínio real
  3. Limpe os cookies e o local storage do navegador
  4. Verifique se todos os serviços estão rodando: docker compose ps

Problemas específicos do Windows

Estes valem para rodar o Studio a partir do código-fonte em desenvolvimento, não para os deployments em Docker ou Kubernetes, que não são afetados pelo sistema operacional do host.

Erros do Turbopack no Windows: use o WSL2.

wsl --install

Problemas de fim de linha:

# Configure git to use LF
git config --global core.autocrlf input

Ver logs

# All services
docker compose logs -f

# Specific service
docker compose logs -f studio

Workflows agendados nunca executam

A surpresa mais comum da auto-hospedagem.

Docker Compose — verifique se o serviço cron está rodando e leia seus logs:

docker compose -f docker-compose.prod.yml logs --tail=50 cron

Um 401 ali significa que o app e o agendador discordam sobre o CRON_SECRET.

Kubernetes — verifique se os CronJobs existem e estão disparando:

kubectl get cronjobs -n studio
kubectl get jobs -n studio --sort-by=.metadata.creationTimestamp | tail

Um LAST SCHEDULE desatualizado ou jobs falhando geralmente significa que o CRON_SECRET está faltando ou não coincide entre os pods de cron e o app. Chame o endpoint manualmente para ver o código de status:

kubectl exec -n studio deploy/studio-app -- sh -c \
  'curl -s -o /dev/null -w "%{http_code}\n" \
   -H "Authorization: Bearer $CRON_SECRET" \
   http://localhost:3000/api/schedules/execute'

Envolva o comando em sh -c com aspas simples para que $CRON_SECRET seja expandido dentro do pod — caso contrário o seu shell local substitui por um valor vazio e você recebe um 401 enganoso.

401 significa que o segredo não coincide. 202 significa que o endpoint aceitou a execução; isso não diz se algum agendamento estava realmente pendente, então confirme na visão de Logs.

Triggers de Gmail / Drive / Outlook nunca disparam

Esses são triggers de polling, movidos pelos jobs /api/webhooks/poll/* que rodam a cada minuto. Verifique se o agendador está executando-os — docker compose logs cron, ou kubectl get cronjobs -n studio para ver um LAST SCHEDULE recente.

Os triggers de chat do Microsoft Teams são o caso diferente: eles usam uma subscription do Microsoft Graph limitada a cerca de três dias, renovada pelo job renew-subscriptions, que roda duas vezes por dia. Se os triggers do Teams funcionam por alguns dias e depois param, esse job não está rodando. Veja Jobs em Background.

Colaboração quebra com várias réplicas

Duas pessoas editando o mesmo workflow deixam de ver uma à outra, ou o status ao vivo nunca atualiza — sem nenhum erro em lugar algum.

É o Redis. O pub/sub e o adaptador Socket.IO não têm fallback entre pods:

kubectl exec -n studio deploy/studio-app -- printenv REDIS_URL
kubectl exec -n studio deploy/studio-realtime -- printenv REDIS_URL

Os dois pods precisam ter REDIS_URL. No Helm eles compartilham um único Secret, então definir a variável em app.env cobre os dois. Veja Redis.

O app quebra na inicialização com um erro REDIS_TLS_SERVERNAME

REDIS_URL usa rediss:// apontando para um endereço IP puro. Certificados TLS não podem ser verificados contra um IP, então defina REDIS_TLS_SERVERNAME com o nome DNS para o qual o certificado foi emitido — ou use um hostname DNS na URL.

Upload de arquivos falha com um erro de CORS

A política de CORS do bucket não permite a sua origem do Studio. Os uploads vão direto do navegador para o armazenamento de objetos via PUT pré-assinado, então ter a configuração do lado do servidor correta não é suficiente.

Se uploads pequenos funcionam mas arquivos acima de 50 MB falham na finalização, verifique nos logs do app a requisição de listagem de partes do provedor. O servidor finaliza uploads multipart a partir do estado autoritativo do provedor; na S3, a identidade usada precisa de s3:ListMultipartUploadParts. Veja Armazenamento de Objetos.

A saída do agente chega toda de uma vez

Seu proxy reverso está fazendo buffer do stream de resposta. Defina proxy_buffering off (Nginx) ou flush_interval -1 (Caddy). Veja Rede.

Websockets desconectam a cada 30 segundos

O timeout de backend do load balancer está fechando as conexões. No GKE, associe um BackendConfig com timeoutSec: 3600 ao Service do realtime; na AWS, aumente o idle_timeout do ALB. Os clientes reconectam, então isso degrada em vez de quebrar. Veja Rede.

Upload na Knowledge Base falha

Embeddings precisam de um provedor hospedado — defina OPENAI_API_KEY, configure o Azure OpenAI, ou defina KB_EMBEDDING_MODEL=gemini-embedding-001 com uma chave do Gemini. Não existe backend local de embeddings, então Ollama ou vLLM não substituem. Se uma chave estiver definida, confirme que o pgvector está instalado no banco de dados.

Credenciais ilegíveis após uma restauração

As integrações aparecem como conectadas mas falham, ou as chaves de provedor dão erro na descriptografia. A ENCRYPTION_KEY não corresponde ao valor em uso quando o backup foi feito. Não há recuperação — a chave original precisa ser restaurada.

Kubernetes: pods do app nunca ficam prontos

Verifique primeiro o init container de migrations — uma migration que falha bloqueia o rollout deliberadamente:

kubectl logs -n studio deploy/studio-app -c migrations --tail=200
kubectl describe pod -n studio <pod>

Causas comuns: DATABASE_URL inacessível, o usuário do banco sem permissões para criar a extensão vector, ou um OOMKill por memória insuficiente. Veja Upgrades para recuperação de falhas de migration.

Kubernetes: ImagePullBackOff

Ou a tag não existe no registry (rode helm get values studio e confira), ou você está fazendo pull de um registry privado sem global.imagePullSecrets. Ao espelhar as imagens em um registry privado, defina global.useRegistryForAllImages: true — caso contrário as imagens de terceiros continuam apontando para o Docker Hub.

Kubernetes: pod do Postgres em Pending

kubectl describe pvc -n studio

Quase sempre é a ausência de uma StorageClass padrão, a falta de um provisionador de PV instalado, ou uma StorageClass que não suporta ReadWriteOnce. Defina global.storageClass para escolher uma específica.

Onde buscar ajuda

Ainda travado? Escreva para help@seeyu.ai informando o método de deployment, o comando que falhou e a saída dele.