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:

  1. Registre horário, status HTTP, código de erro e mensagem completa, com dados sensíveis mascarados.
  2. Registre nome do modelo, duração, resolução, proporção e quantidade de materiais de referência.
  3. Registre task_id, número do pedido, número de envios e número de consultas.
  4. Guarde uma requisição mínima reproduzível, sem dados pessoais e sem chaves.
  5. Distinga falha de requisição de tarefa failed ou expired.
  6. Verifique se a URL do material é publicamente acessível e se a resposta está lenta.
  7. Confirme cota, concorrência e permissões da conta, descartando 429 e 403.
  8. 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: