# 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".

{% callout type="warn" %}
Essa é a confusão mais comum de quem experimenta a SDK pública pela primeira vez. Leia [Os dois caminhos](/pt-BR/docs/dois-caminhos) para entender quem é dono do shell, e o [passo 02 do tutorial](/pt-BR/docs/tutorial/02-explorar-a-anatomia) para ver o que cada arquivo do scaffold faz. A tela em branco fica óbvia depois desses dois.
{% /callout %}

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

```json
{
  "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:

```json
{ "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):

```bash
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](/pt-BR/docs/recursos/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:

```bash
fayz db apply --yes
```

{% callout type="warn" %}
`--yes` aplica migrations sem pedir confirmação. Use em automação consciente, não como hábito no seu terminal local.
{% /callout %}

Ver também: [Conecte seu agente](/pt-BR/docs/ia/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:

```bash
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:
  ```bash
  lsof -ti:5173 | xargs kill
  ```
- Ou rode em outra porta:
  ```bash
  npm run dev -- --port 5174
  ```
