Códigos de Erro do Log
Quando um envio falha, a mensagem carrega umerrorCode legível por máquina, derivado no servidor a partir do que a plataforma registrou sobre a falha. Você o encontra:
- como
errorCodeemGET /v1/messages(lista) eGET /v1/messages/{messageId}(detalhe) — o mesmo valor para a mesma mensagem nos dois; - como o Código de erro nos detalhes de um envio com falha na tela Logs do painel (
/logs).
errorCode é null quando não há erro, e sempre null em DELIVERED, READ, PLAYED e CANCELED. Ele não é o errorMessage: ramifique pelo errorCode e trate o errorMessage como texto para pessoas — a redação dele não é contrato e pode mudar.
O código é calculado toda vez que a mensagem é lida, e não gravado junto com ela. Por isso um código novo nesta página também aparece em mensagens que falharam antes de ele existir, desde que o que foi gravado sobre a falha já o nomeasse.
Duas mudanças funcionam ao contrário. Elas mudam o que é gravado, então valem só para mensagens que falharem depois do lançamento; uma mensagem que falhou antes mantém o código que tinha, em geral SEND_FAILED:
- o alinhamento dos códigos da Meta no envio, exceto quatro códigos antigos que são corrigidos na leitura (veja Recusado no envio na seção da Meta, abaixo);
- os códigos que o worker agora grava onde antes guardava só texto livre —
MESSAGE_CONTENT_UNAVAILABLE,TEMPLATE_RENDER_FAILED,META_CREDENTIALS_MISSING,WHATSAPP_INSTANCE_NOT_CONNECTED,WHATSAPP_INSTANCE_NOT_CONFIGURED,META_TEMPLATE_OR_TEXT_MISSING,BUTTON_NOT_SENDABLE,FLOW_BUTTON_INDEX_INVALID,MEDIA_DOWNLOAD_FAILED,MEDIA_TRANSCODE_FAILED,PROVIDER_UNREACHABLE,META_DELIVERY_UNKNOWN— e os casos novos de códigos existentes descritos nas linhas deles (FEATURE_NOT_SUPPORTED,META_MEDIA_UPLOAD_ERROR,NUMBER_NOT_FOUND_REMOVED,DELIVERY_TIMEOUT,INVALID_DESTINATIONe os dois códigos de variáveis de template).
Plataforma e entrega
Composição do template e da mensagem
O template ou a mensagem não pôde ser montado ou enviado como está. A maioria destes também é ocode de uma recusa 4xx de POST /v1/messages/send; aqui é a mesma recusa caindo numa mensagem registrada — por uma resposta do Chatwoot ou pelo worker.
Respostas de atendentes no Chatwoot
Uma resposta que um atendente escreveu no Chatwoot e que não pôde ser entregue é registrada como mensagemFAILED do número, com origin: "CHATWOOT".
Numa inbox de espelho por API, todo código desta tabela, menos o CHATWOOT_SEND_EXCEPTION, é uma recusa que não é retentada, e o atendente a vê também no Chatwoot: a resposta fica marcada como falha, com o motivo na bolha, e uma nota privada na conversa explica o porquê.
Numa inbox nativa WhatsApp Cloud nenhum destes códigos se aplica: o próprio Chatwoot envia a resposta à Meta, pela camada Meta. Uma resposta que a Meta recusa de imediato não é registrada. Uma resposta que a Meta aceita e depois falha aparece como FAILED com errorCode: null.
Cobrança de número extra sem pagamento
NUMBER_BLOCKED é também o código de uma mensagem que não foi enviada porque a cobrança do número extra do número está sem pagamento. Um número extra é cobrado quando conecta pela primeira vez. Quando essa cobrança é recusada, o número continua conectado, mas o envio por ele fica bloqueado até o pagamento. Isso vale para todo envio, não só para respostas do Chatwoot:
POST /v1/messages/sendePOST /v1/messages/{id}/resendrespondem409 NUMBER_BLOCKEDcomreason: "extra_charge_unpaid". Nada entra na fila.- Uma mensagem que já estava na fila quando o bloqueio começou não é enviada. Ela fica
FAILEDcomerrorCode: "NUMBER_BLOCKED", e não é retentada.
reason vem no 409, não na mensagem gravada. Para confirmar a causa de uma mensagem FAILED, leia o extraChargeUnpaidSince do número (GET /v1/numbers/{id}): ele fica preenchido enquanto a cobrança está sem pagamento.
O que fazer: pague a cobrança e envie a mensagem de novo. Qualquer uma destas ações remove o bloqueio:
- recarregar a carteira ou salvar um cartão — os dois retentam a cobrança automaticamente;
- Pagar agora na página Números do painel (só o proprietário do workspace);
POST /v1/numbers/{id}/pay.
Preparação de mídia em números oficiais
Antes de uma mensagem com mídia ir para a Meta, a Pilot Status baixa o arquivo e, quando precisa, o converte.Números não oficiais (web)
Números oficiais — Meta Cloud API
Num número oficial, o envelope nativo de webhook da Meta traz o erro numérico emstatuses[].errors[].code. A coluna Código Meta é como você liga esse número ao errorCode. — quer dizer que não há número de erro da Meta por trás do código: a plataforma recusou o envio antes de ele chegar à Meta (o META_MEDIA_TOO_LARGE, por exemplo, é uma verificação de tamanho), nenhuma resposta voltou para ler um (META_DELIVERY_UNKNOWN), ou — no caso do META_TOKEN_EXPIRED — nenhum número o mapeia mais.
Quando a Meta não manda número, ou manda um que esta tabela não mapeia, a falha é classificada pelo texto do erro da Meta, e cai em META_SEND_FAILED quando o texto também não bate.
Recusado no envio: os mesmos códigos, com alguns refinamentos
Recusado no envio: os mesmos códigos, com alguns refinamentos
A Meta pode recusar um envio de dois jeitos: na própria requisição de envio, antes de existir um wamid, ou depois, em
statuses[]. Quando o caminho do envio dá um código para um número da Meta, é o mesmo código que o webhook dá (a coluna acima). Quando não dá, o envio sai como META_SEND_FAILED, com o motivo da própria Meta no errorMessage.Uma recusa no envio traz informação que um webhook de status nunca traz — um subcódigo, a redação da Meta, se a chamada era uma operação de grupo —, então algumas respostas são mais específicas:Mensagens que falharam antes deste alinhamento são corrigidas na leitura quando o código antigo não é ambíguo. Quatro códigos que o caminho do envio não grava mais vinham cada um de um único número da Meta, então uma mensagem antiga que traz um deles é lida com o código de hoje:
META_SPAM_RATE_LIMITED (4, 80007) como META_RATE_LIMITED, META_TEMPLATE_BAD_PARAM (131052) como META_MEDIA_DOWNLOAD_ERROR, META_BAD_REQUEST (100 simples) como META_INVALID_PARAM, e META_UPLOAD_SESSION_INVALID (131000) como META_GENERIC_ERROR. Dois ficam como foram gravados, porque o código antigo é ambíguo: um 131048 antigo recusado no envio continua como META_NO_CONVERSATION (que também quer dizer o 131026 do webhook), e um 131053 antigo recusado no envio continua como META_TEMPLATE_NOT_APPROVED (que também quer dizer a nossa pré-checagem).Códigos coringa
O
SEND_FAILED fica de propósito onde não há veredito para nomear: o texto de erro do próprio provedor num número não oficial — na última tentativa, ou num status de falha que o provedor reporta — quando não bate com nenhum código acima; uma falha de rede no upload de mídia para a Meta, fora a de provedor inalcançável (a mensagem em si nunca foi enviada, então é uma falha simples, não META_DELIVERY_UNKNOWN); e um erro interno inesperado. Um código mais específico ali seria um palpite.
BUTTON_NOT_SENDABLE, CHATWOOT_SEND_EXCEPTION, FEATURE_NOT_SUPPORTED, FLOW_BUTTON_INDEX_INVALID, FLOW_REQUIRES_META_NUMBER, MEDIA_DOWNLOAD_FAILED, MEDIA_REHOST_FAILED, MEDIA_TRANSCODE_FAILED, META_CREDENTIALS_MISSING, META_DELIVERY_UNKNOWN, META_MEDIA_UPLOAD_ERROR, META_TEMPLATE_OR_TEXT_MISSING, NUMBER_BLOCKED, NUMBER_NOT_FOUND_REMOVED, PAYMENT_ORDER_PARTIAL_SEND, PROVIDER_UNREACHABLE, TEMPLATE_RENDER_FAILED e WHATSAPP_INSTANCE_NOT_CONNECTED podem ser registrados com o erro de origem anexado depois do código. O errorCode que você recebe continua exato, e esse texto anexado, do provedor ou da exceção, fica interno: ele não é copiado para o errorMessage.Uma mensagem
CANCELED (cancelada via DELETE /v1/messages/cancel) não é um erro de entrega e não carrega um desses códigos.Códigos de erro do webhook vs da API
Num número oficial não existe evento canônicomessage.*: a falha chega no envelope nativo da Meta como statuses[].errors[].code, que a coluna Código Meta acima mapeia. Num número não oficial (web) o message.failed é despachado, mas o código dele não é o errorCode desta página. Ele é anterior, usa valores próprios, e a maioria dos caminhos de falha não manda código nenhum. O payload fica como está de propósito: quem já assina ramifica por ele.
Para reconciliar, use o valor da API. Consulte GET /v1/messages/{messageId} com o id ou o correlationId da mensagem. O errorCode dele é o que bate com esta página, com GET /v1/messages e com a tela de Logs.
Numa mensagem que falhou antes do lançamento, as quatro últimas linhas ainda podem mostrar o valor antigo — em geral
SEND_FAILED, às vezes DELIVERY_TIMEOUT. As linhas sem código trazem o motivo como texto em data.errorMessage. As linhas com code no nível de cima, e a do prazo vencido na retentativa, mandam um corpo plano em vez de { event, data }: internalMessageId, correlationId, destinationNumber, status, error e timestamp ficam no nível de cima.