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) — 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; para o passo a passo de diagnóstico, Fluxo de diagnóstico; para as regras normativas do app, Contrato de App Nebular.
Erros de ativação (o app subiu e não ficou de pé)
Seção intitulada “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
Seção intitulada “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:
- Escute em
0.0.0.0:$PORT(a Nebular injetaPORT), nunca em127.0.0.1,localhostou porta fixa. Portas abaixo de 1024 não existem no runtime. - Garanta que a
portdeclarada no serviço é a mesma em que o app escuta. - Abra a porta antes de qualquer trabalho pesado (migration, aquecimento de cache, chamada a terceiros).
- Confira o
healthcheck_path: ele precisa responder2xx/3xxsem efeitos colaterais. Se devolve4xx/5xx, o app conta como sem HTTP.
Culpa: código do app. Detalhe em Contrato de App e App pronto para escalar.
activate_readonly_write
Seção intitulada “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:
- Descubra o caminho que o app quis gravar (a mensagem do erro traz o caminho; o log do container confirma).
- Se é dado temporário, aponte-o para
/tmpou$TMPDIR. - Se é dado que precisa sobreviver ao deploy (banco SQLite, uploads, índice), monte um volume nesse caminho e leia o caminho de uma variável de ambiente (
DB_FILE,DATA_DIR), nunca fixo no código. - 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 — recomendado para apps sem estado que escalam. A plataforma também pode ter registrado uma sugestão de persistência 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
Seção intitulada “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:
- Leia o log do container (Logs) — a causa quase sempre está na primeira linha de erro.
- 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. - Conexão recusada a um banco (
connection refusednuma 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) ou, para SQLite, migre para libSQL gerenciado.
- 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
Seção intitulada “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:
- Reduza o consumo: diminua caches em memória, concorrência, tamanho de pool e workers.
- Procure vazamentos (memória que só cresce) no log e nas métricas.
- Se o consumo é legítimo, suba
resources.memory_mbdo serviço ou troque de plano (Escala e recursos).
Culpa: código do app (consumo) ou configuração (limite baixo demais para a carga real).
image_requires_root
Seção intitulada “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:
- Declare
build.userno serviço (uid[:gid], nunca root) com um usuário que a imagem suporte. - Ou troque por uma variante da imagem sem privilégio (muitas imagens oficiais têm tag
-nonroot/-slimcom usuário não-root). - 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).
Erros de build (o artefato não foi produzido)
Seção intitulada “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
Seção intitulada “build_clone_failed”O que significa: a plataforma não conseguiu clonar o repositório.
Como corrigir:
- Confira o repositório e a branch configurados no serviço.
- Confira a instalação do GitHub App no serviço (acesso ao repositório pode ter sido revogado).
- Em repositório privado, confirme que a instalação cobre aquele repositório.
Culpa: configuração (acesso/repo/branch), raramente do app.
detect_failed
Seção intitulada “detect_failed”
O que significa: a plataforma não conseguiu detectar automaticamente a stack do app (qual builder usar).
Como corrigir:
- Declare
build.builderexplicitamente no serviço (ex.:nixpacks,dockerfile) em vez de depender da detecção. - Em monorepo, defina o
root_dircorreto para a plataforma olhar a pasta certa (Monorepo). - 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
Seção intitulada “install_failed”
O que significa: a instalação de dependências falhou (o gerenciador de pacotes retornou erro).
Como corrigir:
- Leia o log de build: ele traz a dependência e o motivo (versão inexistente, rede, conflito de resolução).
- Fixe versões e comite o lockfile (
package-lock.json,go.sum,Cargo.lock,poetry.lock) — build não deve resolver “latest”. - 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
Seção intitulada “script_failed”
O que significa: o comando de build (compilar/empacotar) retornou código diferente de 0.
Como corrigir:
- Reproduza o build localmente com o mesmo comando; corrija o erro de compilação/empacotamento.
- Se o comando detectado não é o que você quer, declare
build_commandexplicitamente no serviço. - Garanta que o artefato sai no caminho esperado (em Go, o binário deve sair em
/app/app; veja Go).
Culpa: código do app (erro de build) ou configuração (build_command errado).
build_copy_failed
Seção intitulada “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:
- Confirme o caminho de saída do artefato (binário/bundle) e alinhe-o ao esperado (ex.:
/app/appem Go). - Em monorepo, confira
root_dire os caminhos relativos dobuild_command. - Verifique que o build realmente gerou o arquivo (um
build_commandque “passa” sem produzir saída cai aqui).
Culpa: código do app / configuração (caminho de saída).
build_failed
Seção intitulada “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:
- Leia o log de build de cima para baixo: a primeira linha de erro aponta a fase real (clone, detect, install, script, copy).
- Vá para a seção específica desta página conforme a fase (install_failed, script_failed, detect_failed, build_copy_failed, build_clone_failed).
- Se nenhuma fase se encaixa e o app está correto, não é culpa do app — reporte o
error_code, oiddo deploy e a hora.
Culpa: depende da fase que o log revela.
O que significa: o build estourou a memória disponível e foi encerrado (distinto de activate_oom, que é no runtime).
Como corrigir:
- Reduza o paralelismo do build (ex.:
-j1/--max-old-space-sizemenor, menos workers). - Tire etapas pesadas do build (geração de assets gigantes, testes no build).
- Reduza o que entra no artefato (
.dockerignore, menos dependências de build).
Culpa: código do app (build pesado).
timeout
Seção intitulada “timeout”
O que significa: o build passou do tempo máximo permitido.
Como corrigir:
- Enxugue o build: cache de dependências via lockfile, menos etapas, nada de download gigante a cada build.
- Tire testes e tarefas longas do caminho de build.
- Em multi-stage, remova estágios que não contribuem para a imagem final.
Culpa: código do app (build longo).
disk_full
Seção intitulada “disk_full”
O que significa: o espaço de build encheu durante a produção do artefato.
Como corrigir:
- 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). - Evite copiar
node_modules/alvos de build para a imagem final. - 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 oerror_code, oiddo 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}})
Seção intitulada “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.
unresolved_reference
Seção intitulada “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:
- Para cada nome na lista, crie a variável ou o serviço citado, ou corrija o nome na referência.
- Se a referência aponta para um banco que não existe, crie o banco gerenciado e ligue por
${{<db>.DATABASE_URL}}(a plataforma pode ter registrado uma sugestão). - Refaça o deploy.
Culpa: configuração do app (referência para algo que falta).
reference_cycle
Seção intitulada “reference_cycle”O que significa: há um ciclo — A referencia B que referencia A (direta ou indiretamente).
Como corrigir:
- Siga a cadeia em
details.referencese identifique o laço. - Quebre o ciclo usando um valor literal em um dos lados em vez da referência.
- Refaça o deploy.
Culpa: configuração do app.
invalid_reference
Seção intitulada “invalid_reference”O que significa: um ${{...}} está fora da forma escopo.VAR (sintaxe inválida).
Como corrigir:
- Use exatamente
${{<serviço>.VAR}}ou${{shared.VAR}}— sem espaços estranhos, sem escopo vazio, sem.a mais. - Confira a grafia do nome do serviço e da variável.
- Refaça o deploy.
Culpa: configuração do app (sintaxe).
reference_too_deep
Seção intitulada “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:
- Achate a cadeia: faça as variáveis apontarem direto para o valor final em vez de encadear.
- Substitua os níveis intermediários por valores literais onde fizer sentido.
- Refaça o deploy.
Culpa: configuração do app (encadeamento excessivo).
value_too_large
Seção intitulada “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:
- Reduza o valor: não guarde arquivos, certificados grandes ou blobs em variável de ambiente.
- Mova conteúdo grande para um volume ou um arquivo gerado no build e aponte a variável para o caminho.
- Refaça o deploy.
Culpa: configuração do app (valor grande demais).
Outros códigos (contexto)
Seção intitulada “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.
Migrar SQLite local para banco gerenciado (libSQL)
Seção intitulada “Migrar SQLite local para banco gerenciado (libSQL)”
Quando o erro é activate_readonly_write ou 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 (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ção intitulada “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
Seção intitulada “Passos na Nebular”- 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.
- Confirme que as variáveis foram injetadas no serviço:
LIBSQL_URL,DATABASE_URLeLIBSQL_AUTH_TOKEN. São sensíveis — tratadas como segredo, nunca emNEXT_PUBLIC_*/VITE_*nem em log. - Defina as demais envs do app (ex.:
ENV,TOTP_KEY,PUBLIC_BASE_URL) com defaults seguros; falhe no boot se faltar algo crítico. - Escute em
0.0.0.0:$PORT. A Nebular injetaPORT; por exemploLISTEN_ADDR=0.0.0.0:8080. Nunca127.0.0.1/localhost. - 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)
Seção intitulada “Exemplo de cliente — Go (libsql-client-go, com fallback modernc)”É código do seu app (não é chamada à API /v1 da Nebular):
// 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)
Seção intitulada “Exemplo de cliente — Node (@libsql/client no lugar de better-sqlite3)”// 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}` });}- 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 = ONpor 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/tmpou num volume.
Veja também
Seção intitulada “Veja também”- Contrato de App Nebular — as regras normativas cuja violação gera estes erros.
- Sugestões de persistência — como a plataforma detecta falta de volume/banco e oferece criar.
- Tabela de erros · Fluxo de diagnóstico · Deploys e status · Logs.