# Como corrigir cada erro de deploy (cookbook)

**Esta página é o destino do `fix_url` de cada erro de deploy.** Cada `error_code` tem uma seção com âncora estável: o `fix_url` de um erro `activate_readonly_write` aponta para `#activate_readonly_write` aqui. Chegue direto pela âncora, leia **o que significa**, aplique **como corrigir** e confira **de quem é a culpa** (código do app ou configuração da plataforma).

Antes de mexer no código, leia o log de build e o log do container ([Logs](/operacao/logs/)) — o `error_code` diz a categoria, o log diz a causa exata. Para a tabela completa com HTTP e ação (repetir/corrigir/parar), veja [Tabela de erros](/erros/tabela/); para o passo a passo de diagnóstico, [Fluxo de diagnóstico](/erros/fluxo-de-diagnostico/); para as regras normativas do app, [Contrato de App Nebular](/agents/contrato-app/).

:::note[Como ler as âncoras]
O id de cada seção é **exatamente** o `error_code` (ex.: `## activate_oom` gera a âncora `#activate_oom`). Alguns códigos de build também respondem pelo nome canônico com prefixo `build_` (ex.: `#install_failed` e `#build_install_failed` levam à mesma seção).
:::

## Erros de ativação (o app subiu e não ficou de pé)

O build terminou e a plataforma tentou **ativar** o container; ele não respondeu como esperado. Quase sempre é código ou configuração do app.

### activate_no_http

**O que significa:** o app está rodando e estável, mas não respondeu HTTP na porta esperada dentro da janela de ativação.

**Como corrigir:**

1. Escute em `0.0.0.0:$PORT` (a Nebular injeta `PORT`), **nunca** em `127.0.0.1`, `localhost` ou porta fixa. Portas abaixo de 1024 não existem no runtime.
2. Garanta que a `port` declarada no serviço é a mesma em que o app escuta.
3. Abra a porta **antes** de qualquer trabalho pesado (migration, aquecimento de cache, chamada a terceiros).
4. Confira o `healthcheck_path`: ele precisa responder `2xx`/`3xx` sem efeitos colaterais. Se devolve `4xx`/`5xx`, o app conta como sem HTTP.

**Culpa:** código do app. Detalhe em [Contrato de App](/agents/contrato-app/) e [App pronto para escalar](/operacao/app-pronto-para-escalar/).

### activate_readonly_write

**O que significa:** o app tentou gravar num caminho somente-leitura. A raiz e `/app` não aceitam escrita; só volume montado ou `/tmp`/`$TMPDIR` (64 MB, em memória, apagado a cada deploy).

**Como corrigir:**

1. Descubra o caminho que o app quis gravar (a mensagem do erro traz o caminho; o log do container confirma).
2. Se é dado **temporário**, aponte-o para `/tmp` ou `$TMPDIR`.
3. Se é dado que **precisa sobreviver ao deploy** (banco SQLite, uploads, índice), monte um [volume](/conectados/volumes/) nesse caminho e leia o caminho de uma variável de ambiente (`DB_FILE`, `DATA_DIR`), nunca fixo no código.
4. Se o arquivo pode ser **gerado no build** (assets, bundle), gere-o no build, não no boot.

**Banco SQLite gravando em disco somente-leitura?** Em vez de um volume, considere mover o banco para um [banco gerenciado libSQL](#migrar-sqlite-local-para-gerenciado) — recomendado para apps sem estado que escalam. A plataforma também pode ter registrado uma [sugestão de persistência](/conectados/sugestoes-de-persistencia/) para este caso.

**Culpa:** código do app (gravação em caminho errado), resolvida com um recurso da plataforma (volume) ou mudança para banco gerenciado.

### activate_app_crashed

**O que significa:** o app encerrou logo depois de iniciar. A mensagem do erro traz a primeira linha de erro do log.

**Como corrigir:**

1. Leia o log do container ([Logs](/operacao/logs/)) — a causa quase sempre está na primeira linha de erro.
2. As causas mais comuns, em ordem:
   - **Variável de ambiente faltando.** Defina as envs do serviço; o app deve **falhar no boot com mensagem clara** quando falta algo crítico, não cair em silêncio.
   - **Arquivo ausente** (config, template, binário que não saiu no lugar certo).
   - **Escrita em disco somente-leitura** no boot → trate como [`activate_readonly_write`](#activate_readonly_write).
   - **Conexão recusada a um banco** (`connection refused` numa porta de banco) → o serviço não tem banco ligado; ligue por referência (`DATABASE_URL = ${{db.DATABASE_URL}}`, veja [Conexão e referências](/bancos/conexao-e-referencias/)) ou, para SQLite, migre para [libSQL gerenciado](#migrar-sqlite-local-para-gerenciado).
3. Corrija a causa e dispare novo deploy. A versão anterior continua no ar enquanto isso.

**Culpa:** código ou configuração do app. Quando o log mostra tentativa de criar/gravar o arquivo de banco em disco somente-leitura, trate como falta de persistência (volume ou banco gerenciado).

### activate_oom

**O que significa:** o app usou mais memória que o limite do serviço e foi encerrado (OOM) no runtime.

**Como corrigir:**

1. Reduza o consumo: diminua caches em memória, concorrência, tamanho de pool e workers.
2. Procure vazamentos (memória que só cresce) no log e nas métricas.
3. Se o consumo é legítimo, suba `resources.memory_mb` do serviço ou troque de plano ([Escala e recursos](/operacao/escala-e-recursos/)).

**Culpa:** código do app (consumo) ou configuração (limite baixo demais para a carga real).

### image_requires_root

**O que significa:** a imagem declara ou assume `USER root`. A plataforma a força a rodar como `65534` (não-root) e o container encerrou nos primeiros 30 s.

**Como corrigir:**

1. Declare `build.user` no serviço (`uid[:gid]`, **nunca** root) com um usuário que a imagem suporte.
2. Ou troque por uma variante da imagem sem privilégio (muitas imagens oficiais têm tag `-nonroot`/`-slim` com usuário não-root).
3. Garanta que os diretórios que o app escreve pertencem a esse usuário (ou são volume/`/tmp`).

**Culpa:** código do app / imagem. A plataforma não roda container como root por política de isolamento ([Isolamento](/seguranca/isolamento/)).

## Erros de build (o artefato não foi produzido)

A falha aconteceu **antes** de ativar: ao clonar, detectar a stack, instalar, compilar ou copiar o artefato. Leia sempre o log de build primeiro.

### build_clone_failed

**O que significa:** a plataforma não conseguiu clonar o repositório.

**Como corrigir:**

1. Confira o repositório e a branch configurados no serviço.
2. Confira a instalação do GitHub App no serviço (acesso ao repositório pode ter sido revogado).
3. Em repositório privado, confirme que a instalação cobre aquele repositório.

**Culpa:** configuração (acesso/repo/branch), raramente do app.

### detect_failed

<span id="build_detect_failed"></span>

**O que significa:** a plataforma não conseguiu detectar automaticamente a stack do app (qual builder usar).

**Como corrigir:**

1. Declare `build.builder` explicitamente no serviço (ex.: `nixpacks`, `dockerfile`) em vez de depender da detecção.
2. Em monorepo, defina o `root_dir` correto para a plataforma olhar a pasta certa ([Monorepo](/guia/monorepo/)).
3. Confirme que os arquivos-sinal da stack existem na raiz do build (`package.json`, `go.mod`, `requirements.txt`, `Dockerfile`…).

**Culpa:** configuração (builder/`root_dir` não declarados).

### install_failed

<span id="build_install_failed"></span>

**O que significa:** a instalação de dependências falhou (o gerenciador de pacotes retornou erro).

**Como corrigir:**

1. Leia o log de build: ele traz a dependência e o motivo (versão inexistente, rede, conflito de resolução).
2. **Fixe versões** e comite o lockfile (`package-lock.json`, `go.sum`, `Cargo.lock`, `poetry.lock`) — build não deve resolver "latest".
3. Remova dependências que exigem rede fora do registro padrão ou toolchain que não está na imagem de build.

**Culpa:** código do app (dependências/lockfile). Se a falha é claramente de rede transitória, repita o deploy.

### script_failed

<span id="build_script_failed"></span>

**O que significa:** o comando de build (compilar/empacotar) retornou código diferente de 0.

**Como corrigir:**

1. Reproduza o build localmente com o mesmo comando; corrija o erro de compilação/empacotamento.
2. Se o comando detectado não é o que você quer, declare `build_command` explicitamente no serviço.
3. Garanta que o artefato sai no caminho esperado (em Go, o binário **deve** sair em `/app/app`; veja [Go](/guia/go/)).

**Culpa:** código do app (erro de build) ou configuração (`build_command` errado).

### build_copy_failed

**O que significa:** a plataforma não conseguiu copiar o artefato produzido para a imagem final — em geral o artefato não está onde ela espera.

**Como corrigir:**

1. Confirme o caminho de saída do artefato (binário/bundle) e alinhe-o ao esperado (ex.: `/app/app` em Go).
2. Em monorepo, confira `root_dir` e os caminhos relativos do `build_command`.
3. Verifique que o build realmente gerou o arquivo (um `build_command` que "passa" sem produzir saída cai aqui).

**Culpa:** código do app / configuração (caminho de saída).

### build_failed

**O que significa:** falha genérica de build quando a plataforma não classificou uma fase específica. Trate como "leia o log e isole a fase".

**Como corrigir:**

1. Leia o log de build de cima para baixo: a primeira linha de erro aponta a fase real (clone, detect, install, script, copy).
2. Vá para a seção específica desta página conforme a fase ([install_failed](#install_failed), [script_failed](#script_failed), [detect_failed](#detect_failed), [build_copy_failed](#build_copy_failed), [build_clone_failed](#build_clone_failed)).
3. Se nenhuma fase se encaixa e o app está correto, não é culpa do app — reporte o `error_code`, o `id` do deploy e a hora.

**Culpa:** depende da fase que o log revela.

### oom

<span id="build_oom"></span>

**O que significa:** o build estourou a memória disponível e foi encerrado (distinto de [`activate_oom`](#activate_oom), que é no runtime).

**Como corrigir:**

1. Reduza o paralelismo do build (ex.: `-j1`/`--max-old-space-size` menor, menos workers).
2. Tire etapas pesadas do build (geração de assets gigantes, testes no build).
3. Reduza o que entra no artefato (`.dockerignore`, menos dependências de build).

**Culpa:** código do app (build pesado).

### timeout

<span id="build_timeout"></span>

**O que significa:** o build passou do tempo máximo permitido.

**Como corrigir:**

1. Enxugue o build: cache de dependências via lockfile, menos etapas, nada de download gigante a cada build.
2. Tire testes e tarefas longas do caminho de build.
3. Em multi-stage, remova estágios que não contribuem para a imagem final.

**Culpa:** código do app (build longo).

### disk_full

<span id="build_disk_full"></span>

**O que significa:** o espaço de build encheu durante a produção do artefato.

**Como corrigir:**

1. Reduza o tamanho do artefato e dos intermediários (multi-stage descartando camadas de build, `.dockerignore`, limpeza de caches no mesmo passo que os cria).
2. Evite copiar `node_modules`/alvos de build para a imagem final.
3. Se o artefato já é enxuto e o erro persiste, **não é culpa do app**: é falta de espaço na plataforma (aparentada de `build_storage_unavailable`). Reporte o `error_code`, o `id` do deploy e a hora.

**Culpa:** código do app (artefato grande) na maioria dos casos; plataforma quando o artefato é enxuto e o erro persiste.

## Erros de referência entre variáveis (`${{svc.VAR}}`, `${{shared.VAR}}`)

As referências são resolvidas **no deploy**: o `POST` do deploy responde `422` com `details.references` (apenas nomes, nunca valores) e **nada é criado**. Corrija e refaça o deploy. Detalhe em [Variáveis e referências](/conectados/variaveis-e-referencias/).

### unresolved_reference

**O que significa:** a referência aponta para uma variável ou serviço que não existe. A lista `details.references` diz quais.

**Como corrigir:**

1. Para cada nome na lista, crie a variável ou o serviço citado, ou corrija o nome na referência.
2. Se a referência aponta para um **banco que não existe**, crie o [banco gerenciado](/bancos/postgres/) e ligue por `${{<db>.DATABASE_URL}}` (a plataforma pode ter registrado uma [sugestão](/conectados/sugestoes-de-persistencia/)).
3. Refaça o deploy.

**Culpa:** configuração do app (referência para algo que falta).

### reference_cycle

**O que significa:** há um ciclo — `A` referencia `B` que referencia `A` (direta ou indiretamente).

**Como corrigir:**

1. Siga a cadeia em `details.references` e identifique o laço.
2. Quebre o ciclo usando um **valor literal** em um dos lados em vez da referência.
3. Refaça o deploy.

**Culpa:** configuração do app.

### invalid_reference

**O que significa:** um `${{...}}` está fora da forma `escopo.VAR` (sintaxe inválida).

**Como corrigir:**

1. Use exatamente `${{<serviço>.VAR}}` ou `${{shared.VAR}}` — sem espaços estranhos, sem escopo vazio, sem `.` a mais.
2. Confira a grafia do nome do serviço e da variável.
3. Refaça o deploy.

**Culpa:** configuração do app (sintaxe).

### reference_too_deep

**O que significa:** a cadeia de referências tem mais de 16 níveis (uma variável que referencia outra, que referencia outra…).

**Como corrigir:**

1. Achate a cadeia: faça as variáveis apontarem direto para o valor final em vez de encadear.
2. Substitua os níveis intermediários por valores literais onde fizer sentido.
3. Refaça o deploy.

**Culpa:** configuração do app (encadeamento excessivo).

### value_too_large

**O que significa:** o valor expandido passou de 64 KiB, ou o ambiente total do serviço passou de 256 KiB.

**Como corrigir:**

1. Reduza o valor: não guarde arquivos, certificados grandes ou blobs em variável de ambiente.
2. Mova conteúdo grande para um [volume](/conectados/volumes/) ou um arquivo gerado no build e aponte a variável para o caminho.
3. Refaça o deploy.

**Culpa:** configuração do app (valor grande demais).

## Outros códigos (contexto)

Não têm âncora de remédio porque a ação é "esperar" ou "reportar", não corrigir o app:

- `team_app_limit`: o time já roda o máximo de apps do plano (a mensagem traz "N de M"). Pare ou remova um app, ou peça ao operador para ampliar o limite; depois repita.
- `build_storage_error`, `build_storage_unavailable`, `build_volume_unavailable`: falha interna de armazenamento de build da **plataforma** (não do seu repo). Repita em alguns minutos; se persistir, reporte.
- `deploy_failed`: genérico sem fase classificada — leia o log e caia na seção específica.
- `blocked`, `canceled`, `superseded`: estados de deploy, não falhas do app — veja [Deploys e status](/operacao/deploys-e-status/).

---

## Migrar SQLite local para banco gerenciado (libSQL)

<span id="migrar-sqlite-local-para-gerenciado"></span>

Quando o erro é [`activate_readonly_write`](#activate_readonly_write) ou [`activate_app_crashed`](#activate_app_crashed) **com o log mostrando tentativa de criar/gravar um arquivo de banco** (`.db`, `.sqlite`) em disco somente-leitura, você tem duas saídas: montar um [volume](/conectados/volumes/) (mantém o SQLite em arquivo) ou **migrar para libSQL gerenciado** (recomendado para apps sem estado que escalam em mais de uma réplica). Esta seção é o caminho de libSQL, já aplicado em 5 apps.

### Regra única (o app decide o modo no boot)

Se `LIBSQL_URL` — ou `DATABASE_URL` começando com `libsql://`, `https://` ou `wss://` — estiver definido, use o **banco remoto** com `LIBSQL_AUTH_TOKEN`. Sem isso, **caia no arquivo local** (fallback). Logue no boot **qual modo está ativo**, sem imprimir o token nem a URL.

### Passos na Nebular

1. **No deploy que falhou, aceite a sugestão de banco** (ou ligue o modo "presumir tudo" para a plataforma criar e ligar o recurso sugerido sem perguntar a cada passo). Veja [Sugestões de persistência](/conectados/sugestoes-de-persistencia/).
2. **Confirme que as variáveis foram injetadas** no serviço: `LIBSQL_URL`, `DATABASE_URL` e `LIBSQL_AUTH_TOKEN`. São **sensíveis** — tratadas como segredo, nunca em `NEXT_PUBLIC_*`/`VITE_*` nem em log.
3. **Defina as demais envs do app** (ex.: `ENV`, `TOTP_KEY`, `PUBLIC_BASE_URL`) com defaults seguros; falhe no boot se faltar algo crítico.
4. **Escute em `0.0.0.0:$PORT`.** A Nebular injeta `PORT`; por exemplo `LISTEN_ADDR=0.0.0.0:8080`. Nunca `127.0.0.1`/`localhost`.
5. **Redeploy.** O novo deploy sobe já falando com o banco remoto; o log do boot deve dizer "modo: libSQL remoto".

### Exemplo de cliente — Go (`libsql-client-go`, com fallback `modernc`)

É código do **seu app** (não é chamada à API `/v1` da Nebular):

```go
// abrirBanco escolhe o modo pelo ambiente: se há LIBSQL_URL (ou DATABASE_URL
// remoto), abre o banco gerenciado; senão cai no arquivo local. Chamada uma vez
// no boot, antes de abrir a porta HTTP.
func abrirBanco() (*sql.DB, error) {
	url := primeiroNaoVazio(os.Getenv("LIBSQL_URL"), os.Getenv("DATABASE_URL"))
	if ehRemoto(url) { // libsql:// | https:// | wss://
		token := os.Getenv("LIBSQL_AUTH_TOKEN")
		dsn := url + "?authToken=" + token
		log.Println("banco modo=libSQL-remoto") // nunca logar url/token
		return sql.Open("libsql", dsn)           // github.com/tursodatabase/libsql-client-go
	}
	caminho := primeiroNaoVazio(os.Getenv("DB_FILE"), "/tmp/app.db")
	log.Printf("banco modo=arquivo-local path=%s", caminho)
	return sql.Open("sqlite", caminho) // modernc.org/sqlite, sem CGO
}
```

### Exemplo de cliente — Node (`@libsql/client` no lugar de `better-sqlite3`)

```js
// criarCliente escolhe o modo pelo ambiente e devolve um cliente @libsql/client.
// Chamada no boot; o mesmo cliente serve arquivo local e banco remoto.
import { createClient } from "@libsql/client";

export function criarCliente() {
  const url = process.env.LIBSQL_URL || process.env.DATABASE_URL || "";
  const remoto = /^(libsql|https|wss):\/\//.test(url);
  if (remoto) {
    console.log("banco modo=libSQL-remoto"); // nunca logar url/token
    return createClient({ url, authToken: process.env.LIBSQL_AUTH_TOKEN });
  }
  const file = process.env.DB_FILE || "/tmp/app.db";
  console.log(`banco modo=arquivo-local path=${file}`);
  return createClient({ url: `file:${file}` });
}
```

### Avisos

- **Dados já gravados no arquivo local NÃO migram sozinhos** para o remoto. Exporte e importe o conteúdo explicitamente (dump do SQLite → carga no libSQL) antes de depender só do remoto.
- **Valide o que não vem de graça no remoto:** migrations aplicadas, triggers, índices e **FTS5** recriados, e `PRAGMA foreign_keys = ON` por conexão (não é herdado do arquivo local).
- Mantenha o **fallback local** funcionando para desenvolvimento e teste: sem `LIBSQL_URL`, o app continua subindo contra um arquivo em `/tmp` ou num [volume](/conectados/volumes/).

---

## Veja também

- [Contrato de App Nebular](/agents/contrato-app/) — as regras normativas cuja violação gera estes erros.
- [Sugestões de persistência](/conectados/sugestoes-de-persistencia/) — como a plataforma detecta falta de volume/banco e oferece criar.
- [Tabela de erros](/erros/tabela/) · [Fluxo de diagnóstico](/erros/fluxo-de-diagnostico/) · [Deploys e status](/operacao/deploys-e-status/) · [Logs](/operacao/logs/).
