> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Go: erros e novas tentativas

> Trate o *APIError no SDK Go: status, código e mensagem, errors.As e errors.Is, códigos do SDK, constantes Code, novas tentativas, timeouts e rate limits.

Toda falha da API, de rede ou local é de um único tipo: `*squarecloud.APIError`. Inspecione-o com `errors.As`.

Os trechos mais curtos abaixo rodam dentro do programa de [Executando os exemplos](/pt-br/sdks/go/client#executando-os-exemplos): cole um de cada vez em `main` e execute o `goimports`.

```go theme={"system"}
package main

import (
	"context"
	"errors"
	"fmt"
	"os"

	"github.com/squarecloudofc/sdk-api-go/v3"
)

func main() {
	ctx := context.Background()
	c := squarecloud.New(os.Getenv("SQUARECLOUD_API_KEY"))
	appID := "abc123def456abc123def456"

	err := c.Apps.Start(ctx, appID)

	var apiErr *squarecloud.APIError
	if errors.As(err, &apiErr) {
		fmt.Println(apiErr.Status, apiErr.Code, apiErr.Message)
		fmt.Println(apiErr.Method, apiErr.Path) // "POST" "/v2/apps/<id>/start"
	}
}
```

## `APIError`

| Campo | Tipo | Descrição |
| - | - | - |
| `Status` | `int` | Status HTTP. `0` quando nenhuma resposta chegou (erro de rede, timeout, verificação local) |
| `Code` | `string` | O código de erro da API, por exemplo `APP_NOT_FOUND`, ou um dos códigos do SDK. Compare-o com as [constantes `Code*`](#constantes-code) |
| `Message` | `string` | A explicação do servidor. `""` quando o servidor enviou apenas um código |
| `Method` | `string` | Método HTTP da chamada que falhou |
| `Path` | `string` | Caminho da URL da chamada que falhou, sem a query string |

`Unwrap()` retorna a causa (o erro de transporte, de decodificação ou do context) para `NETWORK_ERROR`, `TIMEOUT` e JSON inválido, ou `nil`. `Error()` gera `squarecloud: <METHOD> <path>: HTTP <status> <CODE>: <message>`, sem `HTTP <status>` quando o status é `0` e sem `: <message>` quando ela está vazia. Compare pelos campos, não por esse texto.

### Contexts cancelados e expirados

Uma chamada cujo `ctx` é cancelado retorna um `*APIError` com `NETWORK_ERROR`, e uma cujo prazo expira retorna `TIMEOUT`, ambos com status `0`. Eles fazem unwrap para o erro do context:

```go theme={"system"}
_, err := c.Apps.Get(ctx, appID)

switch {
case errors.Is(err, context.Canceled):
	// you canceled ctx
case errors.Is(err, context.DeadlineExceeded):
	// the deadline of ctx, or the default one, passed
}
```

Algumas falhas não são `*APIError`:

* [`Realtime.Next`](/pt-br/sdks/go/realtime#encerrando-o-stream) retorna o `ctx.Err()` puro quando seu `ctx` termina, e `io.EOF` quando o stream termina normalmente.
* Problemas do lado de quem chama são erros simples: um reader de upload `nil`, uma URL de snapshot ou URL base que não pode ser interpretada, uma entrada que o `encoding/json` não consegue codificar e um erro do `io.Writer` passado para `DownloadSnapshot`.

## Códigos do SDK

| Status | Código | Constante | Quando |
| - | - | - | - |
| 0 | `NETWORK_ERROR` | `CodeNetworkError` | Sem resposta (DNS, conexão reiniciada, corpo cortado), ou `ctx` cancelado. O erro original está em `Unwrap()` |
| 0 | `TIMEOUT` | `CodeTimeout` | Sem resposta antes do prazo (veja [Timeouts](/pt-br/sdks/go/client#timeouts)) |
| 0 | `FILE_TOO_LARGE` | `CodeFileTooLarge` | Verificação local: um upload acima de 100 MB ou um `Files.Write` acima de 10 MB. Nada foi enviado |
| 0 | `INVALID_ID` | `CodeInvalidID` | Verificação local: um id vazio, `.` ou `..`. Nada foi enviado |
| 0 | `INVALID_API_KEY` | `CodeInvalidAPIKey` | Verificação local: o cliente foi criado com uma chave vazia. Toda chamada, exceto `Service.Status`. Apenas no SDK Go |
| qualquer | `UNKNOWN_ERROR` | `CodeUnknown` | Uma resposta sem código (como uma página de erro de proxy), com o `Status` real e a mensagem `HTTP <status>`. Um corpo 2xx que não é JSON tem a mensagem `Invalid JSON in HTTP <status> response` |

## Constantes `Code*`

`Code` é uma `string` simples. O pacote tem uma constante por código público da API, nomeada a partir dele no estilo Go (`CodeAppNotFound` para `APP_NOT_FOUND`, `CodeInvalidID`, `CodeDNSFailed`, ...), além dos códigos próprios do SDK acima. `CodeRateLimit` (`RATE_LIMIT`) e `CodeRateLimitExceeded` (`RATE_LIMIT_EXCEEDED`) continuam exportadas, marcadas como depreciadas: a API agora responde `RATE_LIMITED` (`CodeRateLimited`) para os dois.

A lista de códigos da API cresce. **Trate um código desconhecido pelo seu status HTTP**:

```go theme={"system"}
func handle(err error) error {
	var apiErr *squarecloud.APIError
	if !errors.As(err, &apiErr) {
		return err // not from the SDK
	}

	switch apiErr.Code {
	case squarecloud.CodeAppNotFound, squarecloud.CodeContainerAlreadyStarted:
		return nil // expected: nothing to do
	}
	switch {
	case apiErr.Status == 429:
		log.Printf("rate limited, try again later: %v", apiErr)
	case apiErr.Status >= 500:
		log.Printf("Square Cloud had a server error: %v", apiErr)
	}
	return err
}
```

## Códigos de erro da API

Todos os outros códigos vêm da API. A [referência de erros da API](/pt-br/api-reference/errors) lista cada um com o status HTTP, o significado e a solução, e cada página do SDK lista os códigos que os seus métodos retornam com mais frequência. Qualquer chamada também pode responder 401 `ACCESS_DENIED` (uma chave inválida), 403 `MISSING_SCOPE` ou `RESOURCE_NOT_ALLOWED` (os [limites da chave](/pt-br/sdks/go/client#chave-de-api-e-escopos)), 429 (veja [Rate limits](#rate-limits)) ou 503 `DATABASE_UNAVAILABLE`.

Os erros de `AI.Chat` usam, em vez disso, códigos da OpenAI em minúsculas (`access_denied`, `rate_limit_exceeded`, `server_overloaded`, ...), que `Code` carrega literalmente. Veja [IA](/pt-br/sdks/go/ai#erros).

## Novas tentativas

O SDK só tenta novamente o que é seguro repetir, até `WithMaxRetries` vezes (padrão `2`, ou seja, até 3 tentativas):

| Repetido | Métodos |
| - | - |
| `NETWORK_ERROR` | Apenas `GET` (incluindo aberturas de realtime e `DownloadSnapshot` antes da resposta) |
| 503 `UPLOAD_BUSY` | Qualquer método |
| 503 `ANALYTICS_BUSY` | Qualquer método |
| 503 `DATABASE_UNAVAILABLE` | Apenas `GET` |

Ele **nunca** tenta novamente:

* `TIMEOUT`;
* qualquer **429**: `RATE_LIMITED` pode ser um bloqueio de cerca de 30 minutos, e `KEEP_CALM` também não é repetido;
* outros 5xx;
* erros de IA.

O 503 `DATABASE_UNAVAILABLE` pode chegar depois que uma mutação já foi aplicada, então o SDK não o repete fora de `GET`. Repita suas próprias mutações idempotentes se precisar. Um upload só é repetido quando seu corpo pode ser reenviado: um `io.ReaderAt` com tamanho conhecido, como um `*os.File` (veja [Commit e upload](/pt-br/sdks/go/commit_and_upload#entradas-aceitas)).

A espera antes da nova tentativa `n` (começando em 0) é `min(8 s, 500 ms · 2^n) · U(0.5, 1)`: backoff exponencial com jitter de 50% a 100%. Defina `WithMaxRetries(0)` para desativar as novas tentativas.

## Timeouts

`WithTimeout` (30 s) se aplica apenas quando o `ctx` não tem prazo, e um único prazo cobre a chamada inteira, incluindo as novas tentativas e as esperas de backoff. Veja [Timeouts](/pt-br/sdks/go/client#timeouts) para as chamadas com mínimo de 2 minutos e as chamadas sem prazo padrão. Um prazo que expira retorna `TIMEOUT` com status `0`, nunca é repetido e faz unwrap para `context.DeadlineExceeded`.

## Rate limits

Toda conta tem um limite de requisições a cada 60 segundos, definido pelo seu plano ([valores](/pt-br/api-reference/limitations-and-restrictions)), e algumas rotas têm limites próprios:

* **429 `RATE_LIMITED`**: a conta ou a chave de API ultrapassou a sua cota de requisições e fica bloqueada por cerca de 30 minutos, ou um IP que continua enviando chaves inválidas fica bloqueado por um curto período. Também é o limite dos endpoints de rede e de `Account.Snapshots`.
* **429 `KEEP_CALM`**: chamadas demais a uma rota em pouco tempo.

O SDK nunca repete um 429. Diminua o ritmo e aguarde antes de tentar novamente.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Referência de erros da API" icon="book" href="/pt-br/api-reference/errors">
    Todos os códigos de erro, com o significado e a solução.
  </Card>

  <Card title="Limitações e restrições" icon="gauge" href="/pt-br/api-reference/limitations-and-restrictions">
    Os limites de requisições de cada plano.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.