Troubleshooting
Os problemas mais comuns ao construir com a Fayz SDK — cada um no formato problema → causa → solução. Comece pela tela em branco: é de longe a dúvida número um de quem chega de fora.
npm run dev abre uma tela placeholder / âncora
Problema. Você gerou o app, rodou npm install && npm run dev, abriu o navegador e viu uma tela mínima — um placeholder, uma âncora vazia, nada do shell de admin que a documentação promete.
Causa. Isso é esperado. O runtime que monta o shell a partir do seu app.manifest.json é distribuído junto com a plataforma Fayz, não no pacote público @fayz-ai/sdk que o scaffold instala hoje. O projeto que você gerou tem o manifesto, os plugins e a config corretos — mas, rodando localmente pela SDK pública, ele ainda não tem o app-runtime que renderiza tudo isso. A tela em branco não é bug: é a fronteira entre o que já é público e o que roda dentro do Fayz.
Solução. Não há um "conserto" — é uma característica do estágio atual. O que fazer:
- Trate o app gerado como fonte da verdade da config: o manifesto, os plugins ligados e a árvore de arquivos já são reais e válidos.
- Para ver o app renderizado hoje, o caminho é rodá-lo dentro da plataforma Fayz.
- Entenda por que essa fronteira existe antes de gastar tempo caçando o "erro".
Essa é a confusão mais comum de quem experimenta a SDK pública pela primeira vez. Leia Os dois caminhos para entender quem é dono do shell, e o passo 02 do tutorial para ver o que cada arquivo do scaffold faz. A tela em branco fica óbvia depois desses dois.
Tela em branco / useAuth must be used inside <AuthProvider>
Problema. Você monta um app em código consumindo os pacotes publicados, sobe o dev server e a tela fica em branco. No console: useAuth must be used inside <AuthProvider> — mesmo com o AuthProvider claramente envolvendo a árvore.
Causa. É um conflito de versões que gera duas cópias do contexto React de auth. Concretamente, na linha 0.6.x: @fayz-ai/saas@0.6.0 depende de plugin-auth ^0.1.0; o npm resolve isso para 0.1.3, que por sua vez exige auth/core ^0.7.1. O resultado é uma segunda cópia de @fayz-ai/auth na árvore de node_modules. O AuthProvider de uma cópia e o useAuth da outra referenciam objetos de contexto React diferentes — então, para o useAuth, não há provider acima dele, e ele lança. A tela em branco é essa exceção derrubando o render.
Solução. Force uma única linha de versão para todo o eixo de auth com um bloco overrides no package.json do app, travado na mesma linha do saas que você usa:
{
"overrides": {
"@fayz-ai/plugin-auth": "0.1.3",
"@fayz-ai/auth": "0.7.1",
"@fayz-ai/core": "0.6.0",
"@fayz-ai/ui": "0.6.0"
}
}
Depois apague node_modules e o lockfile e reinstale (rm -rf node_modules package-lock.json && npm install) para o overrides de fato colapsar as duas cópias em uma. Ajuste os números para casar com as versões do seu @fayz-ai/saas — o ponto é que plugin-auth, auth, core e ui fiquem todos numa linha coerente, sem uma segunda cópia do contexto.
fayz doctor avisa sobre plugins referenciados no manifesto
Problema. Você roda fayz doctor e vê um aviso como:
⚠ manifest references plugin(s) [agenda, crm] — each id must resolve to an installed @fayz-ai/plugin-* factory wired in src/plugins.generated.ts or src/config/app.tsx 0 error(s), 1 warning(s)
Causa. É um aviso, não um erro — repare no 0 error(s). Cada id de plugin no manifesto precisa resolver para uma factory @fayz-ai/plugin-* de fato instalada (via npm) e conectada no src/plugins.generated.ts ou no src/config/app.tsx. Um plugin, no modelo real, é um pacote npm instalado + ligado no array de plugins — não algo que o runtime injeta sozinho. O doctor lista os ids que ainda não estão amarrados para você saber o que falta instalar ou ligar.
Solução. Instale o pacote de cada plugin referenciado (npm i @fayz-ai/plugin-agenda, …) e confirme que ele está ligado no src/plugins.generated.ts ou no src/config/app.tsx. É um aviso, não um erro — a contagem 0 error(s) significa que o build não quebra e o CI não cai; mas cada id listado só vira um plugin carregado depois de instalado e wired.
fayz doctor reprova um tema custom num app código-primeiro
Problema. Você tem um app código-primeiro — o tema real vive no code-config (um SaasTheme com HSL custom, perfeitamente válido) e o app.manifest.json é vestigial. Ainda assim o fayz doctor reprova o manifesto porque theme.brand não é um dos sete nomes de marca conhecidos.
Causa. O doctor hoje valida o manifesto de forma estrita, sem saber que, num app código-primeiro, o manifesto é só um resquício e a fonte da verdade do tema é o code-config. O theme.brand do manifesto aceita apenas os sete nomes de marca embutidos; um HSL custom válido no seu SaasTheme não satisfaz essa checagem porque ela nem olha para o code-config.
Solução. Mantenha, no manifesto vestigial, um theme.brand mínimo e válido — qualquer um dos sete nomes de marca — só para passar no doctor, enquanto o tema real continua no code-config, que é quem de fato pinta o app:
{ "theme": { "brand": "violet" } }
O brand nomeado aqui não afeta o app renderizado (o code-config vence); ele só mantém o manifesto válido. É um workaround honesto, não um bug seu. A validação vai ficar path-aware — reconhecendo apps código-primeiro e deixando o code-config ser a fonte da verdade do tema — num fix de SDK; até lá, o brand nomeado no manifesto é a ponte.
fayz db apply reclama de variáveis de ambiente faltando
Problema.
✗ Missing required Supabase credentials: SUPABASE_PROJECT_REF (or SUPABASE_REF), SUPABASE_PAT (or SUPABASE_ACCESS_TOKEN).
Causa. O fayz db apply fala com a API de gestão do Supabase e nunca assume credenciais padrão. Ele precisa de duas coisas: qual projeto (SUPABASE_PROJECT_REF, ou o alias SUPABASE_REF) e com qual token (SUPABASE_PAT, ou o alias SUPABASE_ACCESS_TOKEN).
Solução. Coloque as duas no seu shell ou em <app>/.env.local (que é git-ignored):
SUPABASE_PROJECT_REF=seu-project-ref SUPABASE_PAT=sbp_...
Onde achar cada uma:
- Access token (PAT): dashboard do Supabase → Account → Access Tokens → Generate new token.
- Project ref: dashboard do Supabase → Project Settings → General (é também o subdomínio na URL do projeto).
O dry-run diz "ships no migrations"
Problema. No fayz db apply --dry-run aparece uma nota:
installed @fayz-ai/db ships no migrations/ — the spine step is empty (upgrade to @fayz-ai/db >= 0.1.3 once published)
Causa. A "espinha" de migrations (o schema base compartilhado) é distribuída dentro do pacote @fayz-ai/db. A versão publicada hoje (0.1.2) ainda não embarca esses arquivos .sql — por isso o passo da espinha sai vazio no plano. O SQL da espinha entra a partir da 0.1.3.
Solução. É esperado enquanto a 0.1.3 não sai. O --dry-run continua mostrando o plano corretamente (incluindo suas migrations próprias); só o passo spine fica vazio. Quando a 0.1.3+ for publicada, um npm install @fayz-ai/db@latest preenche esse passo automaticamente. Veja o Changelog.
db apply se recusa a rodar em shell não interativo
Problema.
✗ Refusing to apply migrations without confirmation in a non-interactive shell. Re-run with --yes to proceed.
Causa. Aplicar migrations é uma operação destrutiva contra um banco real, então o comando pede uma confirmação y. Em um shell sem TTY (CI, pipe, agente de IA), não há como digitar essa confirmação — e o comando se recusa em vez de travar esperando por um stdin que nunca vem.
Solução. Passe --yes (ou -y) para pular o prompt de forma explícita:
fayz db apply --yes
--yes aplica migrations sem pedir confirmação. Use em automação consciente, não como hábito no seu terminal local.
Ver também: Conecte seu agente — como um agente roda os comandos fayz com o AGENTS.md no contexto.
fayz create rejeita o nome do app
Problema.
✗ Provide a kebab-case app name, e.g. fayz create admin my-app
Causa. O nome do app precisa ser kebab-case: só letras minúsculas, números e hífens, começando por letra ou número. Nomes com maiúsculas, espaços, _ ou caracteres especiais (Minha Loja, minha_loja, MinhaLoja) são recusados.
Solução. Use um slug válido:
fayz create admin minha-loja
Porta 5173 já está em uso
Problema. Ao rodar npm run dev o Vite falha ou abre em outra porta porque a 5173 já está ocupada.
Causa. O scaffold usa Vite, cujo servidor de desenvolvimento sobe na porta 5173 por padrão. Outro processo (uma instância anterior que não morreu, outro app Vite) já está segurando a porta.
Solução. Escolha uma:
- Libere a porta matando o processo antigo:
lsof -ti:5173 | xargs kill
- Ou rode em outra porta:
npm run dev -- --port 5174