Os erros do Seedance têm duas camadas: uma é a falha da requisição HTTP, como 401, 403, 400 e 429; a outra é a requisição bem-sucedida cujo trabalho termina em failed ou expired. Considerar sucesso só porque a interface de envio retornou 200 é o erro de julgamento mais comum ao integrar uma API de vídeo. A ordem correta de diagnóstico é: ver o status HTTP, depois o estado da tarefa e o campo error, e só então alterar o prompt ou trocar de modelo.
Este artigo separa os tipos de erro, apresenta causas, ordem de tratamento e um trecho reutilizável de tratamento de erros. Caminhos de interface, nomes de estado e critérios de cota podem mudar entre versões; prevalecem a documentação do site e a documentação do fornecedor.
Nota: Seedance, Doubao e Volcano Engine são marcas da ByteDance e de empresas associadas. Este artigo é apenas uma explicação técnica e não representa vínculo de subordinação ou endosso. Caminhos e campos nos exemplos servem apenas para demonstração; confira a documentação antes de chamar.
1. Distinga primeiro falha de requisição e falha de tarefa
| Sintoma | Camada | Causa comum | Tratamento |
|---|---|---|---|
| 401 | HTTP | Key ausente, formato errado, expirada | Corrigir autenticação |
| 403 | HTTP | Permissão insuficiente, modelo não ativado, restrição de região | Verificar permissão e ativação |
| 400 | HTTP | Parâmetro fora da faixa, nome de modelo errado, material inacessível | Ajustar conforme a documentação |
| 429 | HTTP | Limite de concorrência, taxa ou cota | Backoff, reduzir concorrência |
| 5xx | HTTP | Sobrecarga do upstream ou falha temporária | Backoff, trocar de canal |
| failed | Tarefa | Rejeição de revisão, problema no material, erro de geração | Ler o erro, corrigir o material |
| expired | Tarefa | Tempo esgotado sem conclusão ou sem coleta do resultado | Recriar tarefa, verificar prazo |
| Falha de download | Resultado | URL expirada, autenticação, rede | Obter novamente ou transferir |
O log deve registrar pelo menos horário, status HTTP, código de erro, nome do modelo, task_id, número do pedido de negócio e duração. Não registre a Key completa nem imprima a URL assinada do resultado.
2. 401 e 403: verifique primeiro cabeçalho e Key
401 indica que a identidade não foi validada e normalmente não tem relação com capacidade do modelo nem saldo. Verifique nesta ordem:
- Se
AuthorizationéBearer <key>. O Volcano Ark usa a API Key como Bearer Token. - Se a Key tem espaços, quebras de linha ou aspas extras, e se a variável de ambiente foi realmente carregada.
- Se Base URL e Key pertencem à mesma plataforma e à mesma região.
- Se a Key foi excluída, rotacionada, desativada ou se o projeto não tem permissão.
- Se o proxy reverso sobrescreveu ou descartou o cabeçalho
Authorization.
403 é mais frequentemente permissão: modelo não ativado, conta sem permissão para aquele modelo, restrição de região ou conformidade. Para 401, uma Key nova em uma requisição mínima localiza o problema rapidamente; para 403, verifique o estado de ativação e as permissões no console, pois mudar o código normalmente não resolve.
3. 429: limite de taxa, concorrência e cota
429 indica que a requisição ultrapassou limite de taxa, concorrência ou cota. Cenários comuns:
- Vários serviços compartilham uma Key e disputam a mesma cota.
- Tarefas em lote começam no minuto cheio e criam um pico de tráfego.
- Retentativas sem backoff: quanto mais falha, mais envia, criando uma tempestade.
- Tarefas longas ocupam toda a concorrência, e tarefas curtas não entram na fila.
O princípio é backoff exponencial com jitter, redução de concorrência, separação de Keys por projeto e envio em horários escalonados. Não repita em loop sem backoff; continuar enviando em alta frequência durante o 429 transforma a limitação em falha contínua. Se o negócio realmente precisa de alta concorrência, confirme o teto de cota com antecedência e prepare um canal alternativo.
4. 400: a maioria é erro de parâmetro
O 400 costuma ser localizado diretamente pela mensagem de erro. Confira com atenção:
- Nome e versão do modelo: copie da documentação; não monte sufixos de memória.
- Duração: as faixas variam por modelo; por exemplo, 2.5 vai de 4 a 30 segundos, 2.0 de 4 a 15 segundos e 1.0 de 2 a 12 segundos.
- Resolução e proporção: confirme se o modelo suporta 4K, 21:9 ou adaptive.
- Quantidade de materiais de referência: 2.5 aceita até 30 imagens, 10 vídeos e 10 áudios; 2.0 tem teto menor.
- URL de imagem ou vídeo: precisa ser acessível pela plataforma; não pode ser endereço de rede interna nem link que exige login.
- Tarefas de edição ou continuação: alguns modos permitem apenas duração automática, sem segundos preenchidos manualmente.
- Entrada de áudio: algumas versões não aceitam entrada apenas de áudio.
A forma mais econômica de tempo é usar o corpo de exemplo da documentação para uma reprodução mínima e ir adicionando seus parâmetros um a um. Testando após cada item, você localiza o campo exato.
5. Tarefas failed e expired
Envio bem-sucedido significa apenas que a tarefa entrou na fila. Os estados comuns na consulta incluem queued, running, succeeded, failed e expired. Em failed, leia o campo error: rejeição de revisão de conteúdo, material de entrada irregular, imagem de referência ilegível e erro no processo de geração exigem tratamentos completamente diferentes.
expired costuma ocorrer quando a tarefa ultrapassa o prazo de execução sem concluir ou sem que o resultado seja coletado. Na documentação, execution_expires_after é configurável e o padrão é 48 horas; o ID da tarefa é mantido por 7 dias. Após o prazo, continuar o polling não recupera a tarefa; só resta recriá-la. Ao usar callback, atenção: se o callback não for confirmado em 5 segundos, haverá até 3 novas tentativas, e a interface de callback precisa ser idempotente.
Não tente contornar repetidamente uma rejeição de revisão mudando algumas palavras. Confirme primeiro a licença do material, o direito de imagem das pessoas, os elementos de marca e a política de conteúdo, e só então decida reenviar.
6. Timeout e polling
O timeout deve ser dividido em três camadas: timeout de conexão do cliente, timeout de cada consulta e deadline total da tarefa. A interface de envio normalmente retorna o task_id rápido; o tempo real está na fila e na renderização. Timeout curto demais trata um envio normal como falha; longo demais prende o pool de threads.
Recomenda-se começar o polling em 5 segundos e aumentar gradualmente até 15 a 30 segundos, com um deadline total. Quando houver callback, prefira callback e use polling como reserva. Não reenvie imediatamente após um timeout: verifique primeiro, pelo número do pedido ou chave de idempotência, se já existe tarefa em execução.
7. Falha no download do resultado
Tarefa concluída não significa arquivo em mãos. O video_url costuma ser um endereço temporário assinado, com validade; salvar direto no banco e baixar horas depois gera 403 ou 404 com frequência. Tratamento:
- Após o sucesso, baixe imediatamente em streaming para o seu armazenamento de objetos.
- Se o download falhar, repita apenas o download; não recrie a tarefa de geração.
- Valide
Content-Type, tamanho do arquivo e capacidade de reprodução. - Não imprima a URL assinada completa no log.
8. Exemplo: tratamento de erros com backoff e idempotência
O código abaixo separa envio, polling e download e repete apenas erros transitórios. Caminhos e campos seguem a documentação do site.
import os, time, random, requests
BASE = os.environ["SEEDANCE_BASE_URL"].rstrip("/")
HEADERS = {
"Authorization": f"Bearer {os.environ['SEEDANCE_API_KEY']}",
"Content-Type": "application/json",
}
def submit(payload, max_retries=5):
# antes de chamar, consulte a tabela de tarefas pelo número do pedido; se já houver task_id, reuse
for attempt in range(max_retries):
try:
r = requests.post(
f"{BASE}/contents/generations/tasks",
headers=HEADERS, json=payload, timeout=(5, 30),
)
except requests.Timeout:
time.sleep(min(2 ** attempt, 20) + random.random())
continue
if r.status_code == 429 or r.status_code >= 500:
time.sleep(min(2 ** attempt, 20) + random.random())
continue
if r.status_code >= 400:
raise RuntimeError(f"{r.status_code}: {r.text[:500]}")
return r.json()["id"]
raise RuntimeError("submit retries exhausted")
def wait(task_id, deadline_seconds=900):
deadline = time.time() + deadline_seconds
delay = 5
while time.time() < deadline:
r = requests.get(
f"{BASE}/contents/generations/tasks/{task_id}",
headers=HEADERS, timeout=(5, 30),
)
if r.status_code == 429 or r.status_code >= 500:
time.sleep(delay)
delay = min(delay * 1.5, 30)
continue
r.raise_for_status()
data = r.json()
if data["status"] == "succeeded":
return data["content"]["video_url"]
if data["status"] in ("failed", "expired"):
raise RuntimeError(f"{data['status']}: {data.get('error')}")
time.sleep(delay)
delay = min(delay * 1.5, 30)
raise TimeoutError(task_id)
def download(url, path):
with requests.get(url, stream=True, timeout=(5, 120)) as r:
r.raise_for_status()
with open(path, "wb") as f:
for chunk in r.iter_content(1024 * 256):
f.write(chunk)
O código deliberadamente não repete 400, 401 e 403. Erros de parâmetro e autenticação não passam por mais tentativas; apenas ampliam logs e custos.
9. Retentativa, idempotência e checklist de suporte
A retentativa só serve para erros transitórios: 429, 5xx e timeout de conexão. 400, 401, 403 e rejeição de revisão não devem ser repetidos automaticamente. A chave da idempotência não é o número de tentativas, mas o número do pedido de negócio: consulte a tabela antes de enviar, grave o task_id após o envio e reutilize a tarefa existente em requisições repetidas.
Antes de contatar o fornecedor, organize as informações conforme o checklist:
- Registre horário, status HTTP, código de erro e mensagem completa, com dados sensíveis mascarados.
- Registre nome do modelo, duração, resolução, proporção e quantidade de materiais de referência.
- Registre
task_id, número do pedido, número de envios e número de consultas. - Guarde uma requisição mínima reproduzível, sem dados pessoais e sem chaves.
- Distinga falha de requisição de tarefa
failedouexpired. - Verifique se a URL do material é publicamente acessível e se a resposta está lenta.
- Confirme cota, concorrência e permissões da conta, descartando 429 e 403.
- Anexe o request ID e o horário de reprodução antes de abrir o diagnóstico.
Perguntas frequentes
A interface de envio retornou 200. Por que a tarefa falhou?
200 indica apenas que a tarefa foi criada. A geração de vídeo é assíncrona; o estado final deve ser lido nos campos status e error da consulta.
429 significa saldo insuficiente?
Não necessariamente. O 429 normalmente indica limite de taxa, concorrência ou cota; problema de saldo pode retornar outro erro. Verifique primeiro concorrência, Key compartilhada e política de retentativa.
Posso repetir diretamente depois de uma tarefa failed?
Leia primeiro o error. Rejeição de revisão e material irregular normalmente falham de novo se reenviados sem alteração; falhas de rede ou do upstream podem ser repetidas com backoff. Antes de repetir, faça a verificação de idempotência pelo número do pedido.
Qual é o intervalo adequado de polling?
Comece em 5 segundos e aumente gradualmente até 15 a 30 segundos, com timeout total. Quando houver callback, prefira callback e use polling como reserva.
A URL do resultado não abre. O que fazer?
Na maioria dos casos, a validade expirou ou a assinatura perdeu a vigência. Após o sucesso, transfira imediatamente para o armazenamento de objetos; se já expirou, consulte a tarefa novamente ou recrie a tarefa, sem insistir na URL antiga.
Próximos passos
Crie primeiro uma Key de teste no ZSQH AI Gateway, ensaie uma vez cada caso — 401, 429, erro de parâmetro e falha de tarefa — e confirme que alertas e política de retentativa funcionam. Disponibilidade de modelos e formas de cobrança seguem a página de preços.
Leitura relacionada:
