Auto-retry esgotado após N falhas

Sintoma — saída do cron fetch --deploy:

[SKIP] meu-app  retry exhausted for commit abc1234 (3/3 fails)
                push a new commit or run `runner deploy meu-app` manually

Ou via notificação Telegram:

[Runner] retry-exhausted: meu-app stuck on abc1234

Causa

O cron fetch --deploy (v2.28.0+) tentou deployar o mesmo commit 3 vezes consecutivas — todas falharam. Para evitar loop infinito, o runner marca esse commit como exausto e para de tentar. A app continua rodando na versão anterior; só este commit específico é ignorado pelo cron.

O counter de tentativas reseta automaticamente quando você faz push de um commit novo ou força o deploy manual.

Distinção: retry-exhausted vs auto-pause

São dois mecanismos diferentes. É possível ter os dois ao mesmo tempo.

retry-exhausted — este commit não será mais tentado pelo cron. A app continua em status=running (a versão anterior segue ativa). O cron simplesmente pula o SHA problemático.

auto-pause — a app ficou em status=paused após N erros consecutivos de fetch (rede, GitHub, token inválido). O cron para completamente até runner unpause. Threshold configurado por max_consecutive_fetch_errors (v2.23.19+).

Se runner status meu-app mostrar status=paused, você tem auto-pause. Se mostrar status=running mas o cron está pulando, é retry-exhausted.

Veja Pause/unpause para o fluxo de auto-pause.

Diagnóstico

runner debug last-error meu-app   # PRIMEIRO — erro estruturado do último fail
runner status meu-app             # confirma se está paused ou só retry-exhausted
runner logs history meu-app       # logs das tentativas anteriores

Comece pelo debug last-error — ele mostra a mensagem de erro exata, a versão que falhou e o timestamp. Isso evita investigar no escuro.

Fix — depois de identificar e corrigir o problema

Opção 1: forçar redeploy do mesmo commit

runner deploy meu-app

runner deploy ignora o estado de retry-exhausted e tenta uma vez. Use quando o problema era transitório (rede, GitHub fora, dependência lenta) e o commit em si está correto.

Opção 2: push de commit novo

Faça o fix no código, commit e push para a branch dist. O próximo cron fetch --deploy detecta um SHA novo e reinicia o counter normalmente.

Use quando o problema está no código do commit abc1234.

Opção 3: se também está auto-paused

Se runner status mostrar status=paused:

runner unpause meu-app
runner deploy meu-app

Sempre diagnostique antes de unpause — se o problema original não foi resolvido, a app vai pausar de novo.

Workflow completo

# 1. Recebe notificação ou vê no cron
#    [SKIP] meu-app  retry exhausted for commit abc1234

# 2. Identifica o erro
runner debug last-error meu-app

# 3. Verifica se está paused
runner status meu-app

# 4a. Se o problema é no código: corrige + commit + push
#     próximo fetch --deploy tenta normalmente

# 4b. Se foi transitório (rede, GitHub instável):
runner deploy meu-app

# 4c. Se também está auto-paused:
runner unpause meu-app
runner deploy meu-app

# 5. Confirma que voltou ao normal
runner status meu-app

Como prevenir

Notificações Telegram — você recebe o alerta retry-exhausted assim que acontece, não horas depois. Ver Notificações.

Healthcheck com start_period adequado — se a app leva 45s para bootar mas o healthcheck tem timeout 30s, os 3 retries vão esgotar por timeout, não por bug real. Ajuste start_period ou timeout no manifest.

Não force deploy de commit claramente quebradorunner deploy manual em commit quebrado só gera mais notificações sem resolver o problema. Corrija o código primeiro.

Ver também

By Borlot.com.br on 27/05/2026