Skip to main content

Erros de resolver chegam com HTTP 200

Esta é a coisa mais importante a saber antes de escrever o tratamento de erros. Seguindo a especificação GraphQL over HTTP, uma requisição que chega aos nossos resolvers retorna HTTP 200 mesmo quando uma operação falhou. A falha é informada dentro do corpo da resposta, e não pelo código de status. Portanto, esta verificação não funciona:
Em vez disso, verifique o corpo. Alguns erros de transporte, como o 415 para um Content-Type não suportado, têm o corpo vazio, então verifique se a resposta é JSON antes de fazer o parsing:
Algumas falhas são capturadas antes de qualquer execução. Nenhuma delas chega a um resolver nem consome uma chamada de API:
  • Uma requisição malformada retorna um status de erro: HTTP 400 para JSON inválido ou ausência de query, 413 para um corpo acima de 64 KB, 405 para um método diferente de POST e 415 para um Content-Type não suportado.
  • Uma consulta que não é válida para o schema retorna HTTP 400 somente se sua requisição enviar Accept: application/graphql-response+json. Isso abrange erro de sintaxe, campo desconhecido, tipo de argumento incorreto, valor de enum inválido e uma consulta acima dos limites de consulta. Se você enviar Accept: application/json, ou nenhum cabeçalho Accept, o mesmo erro retorna HTTP 200. Em ambos os casos, o corpo tem um array errors e nenhum data.
Depois que a execução começa, a validação de entrada no nível do resolver e as falhas da API — incluindo autenticação, autorização, limites de taxa upstream e respostas 5xx upstream — retornam HTTP 200 com um array errors.

O formato do erro

Todo erro de resolver carrega seu status de API equivalente ao HTTP em extensions:
  • message — uma descrição legível por humanos. Removemos API Keys e outras credenciais das mensagens de erro dos resolvers, mas um erro sobre um valor que você enviou, como uma variável do tipo errado, pode repetir esse valor. Trate message como possivelmente sensível antes de registrá-la em logs.
  • path — qual campo da sua consulta falhou. Com vários campos em uma requisição, é assim que você identifica qual deles.
  • extensions.status — o status HTTP que a chamada REST equivalente teria retornado. Use-o para decidir o tratamento.
  • extensions.code — o código de erro numérico do Ayrshare, quando o endpoint subjacente fornece um.
  • extensions.retryAfter — presente em respostas 429 de cota ou limite de taxa upstream quando há um intervalo de nova tentativa disponível. Não está presente no 429 do orçamento de despacho por requisição.
Use extensions.code com a referência de códigos de erro ou passe-o para explainError.

Sucesso parcial

Se uma requisição pede várias coisas e apenas algumas têm sucesso, você recebe tanto data quanto errors:
history teve sucesso e seus dados podem ser usados. Apenas analytics precisa de nova tentativa. Não descarte a resposta inteira porque errors está presente — isso jogaria fora dados pelos quais você já foi cobrado.

Sucesso parcial em publicações para várias redes

Uma publicação para várias redes pode ter sucesso em algumas e falhar em outras. Isso não é informado como um erro GraphQL, porque a operação em si funcionou — ela fez exatamente o que você pediu e está informando o que aconteceu. O resultado separa os três desfechos:
  • postIds — redes que publicaram, com as URLs das publicações. Apenas sucessos.
  • errors — redes que falharam, com o motivo.
  • blocked — redes interrompidas antes de uma tentativa, por exemplo pelo circuit breaker por rede após falhas determinísticas repetidas. Elas são separadas das tentativas junto ao provedor que retornaram erros.
status é "error" se qualquer rede falhou, então não é um sinal confiável de que nada foi publicado. Leia postIds para descobrir o que foi.

Novas tentativas

A API GraphQL nunca faz novas tentativas automaticamente. Se uma requisição falhar, nada foi tentado novamente em silêncio em seu nome. Isso importa principalmente para mutations. createPost expõe idempotencyKey: gere uma chave única antes da primeira tentativa e, depois, reutilize a mesma chave e um payload idêntico em cada nova tentativa. Uma nova tentativa já resolvida reproduz o resultado original em vez de repetir a escrita. Não troque para uma nova chave após uma resposta ambígua. boostFacebookPost e instagramBoostPost também recebem um idempotencyKey, e ele protege dinheiro de verdade. Uma nova tentativa com a mesma chave e os mesmos argumentos retorna o resultado original, marcado com idempotentReplayed: true, em vez de criar e pagar por um segundo anúncio. Uma chave cobre sua conta inteira nas duas plataformas da Meta, então nunca reutilize a chave de um boost do Facebook para um boost do Instagram. Quando uma chave é recusada, extensions.status informa o motivo. createPost retorna 409 enquanto a primeira tentativa ainda está sendo processada, então aguarde e tente novamente com a mesma chave, e 400 quando o payload difere do da primeira tentativa. As mutations de boost retornam 409 em ambos os casos e também quando a chave foi usada para um boost na outra plataforma. Outras escritas, como addComment, não têm chave de idempotência. Se a resposta delas se perder, verifique a rede social ou o estado da API antes de decidir se outra tentativa é segura. Dois limites diferentes informam 429, e eles exigem tratamentos diferentes. O orçamento de despacho só rejeita campos raiz depois que cinco chamadas de API já foram iniciadas na mesma requisição, e sua mensagem começa com Query exceeds the per-request dispatch budget: divida esses campos em requisições de no máximo cinco, sem necessidade de aguardar. Qualquer outro 429 é um limite de taxa ou de cota: aguarde extensions.retryAfter segundos quando estiver presente; caso contrário, aplique um backoff antes de tentar novamente, e tente novamente apenas os campos que falharam. Para um 5xx em uma leitura, tentar novamente é seguro, com uma exceção: generatePost é uma query, mas uma nova tentativa chama o gerador de IA de novo, conta como outra chamada de API e retorna um texto diferente. Para um 5xx em uma escrita sem idempotência, confirme se ela teve efeito antes de tentar novamente.

Status comuns

Erros gerados pelo próprio GraphQL antes da execução, como um campo desconhecido, um tipo de argumento incorreto ou um valor de enum inválido, não têm extensions.status. Eles retornam HTTP 400 ou 200 dependendo do seu cabeçalho Accept, conforme descrito acima. Eles significam que a própria consulta está errada, e nenhuma chamada de API foi feita ou cobrada.