> ## 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.

# Erros e novas tentativas

> SquareCloudBlobError, a lista de BlobErrorCode, os erros de rede que não são encapsulados e exatamente quais chamadas o @squarecloud/blob tenta novamente.

## `SquareCloudBlobError`

Toda falha da API lança um `SquareCloudBlobError`.

| Propriedade           | Tipo                      | Descrição                                                                                                              |
| --------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `status`              | `number`                  | Status HTTP da resposta.                                                                                               |
| `code`                | `BlobErrorCode`           | O código de erro da API, por exemplo `OBJECT_NOT_FOUND`.                                                               |
| `message`             | `string`                  | A explicação do servidor, ou o código quando não há nenhuma.                                                           |
| `extra`               | `Record<string, unknown>` | Todos os outros campos do corpo do erro, por exemplo `prefix` em erros de regras.                                      |
| `isUpgradeRequired()` | `() => boolean`           | `true` para `UPGRADE_REQUIRED`, o código de toda recusa do plano (limite, recurso ou plano). A `message` informa qual. |

```typescript theme={"system"}
import { SquareCloudBlob, SquareCloudBlobError } from "@squarecloud/blob";

const blob = new SquareCloudBlob(process.env.SQUARECLOUD_API_KEY);

try {
    await blob.shares.create(id, { password: "secret123" });
} catch (error) {
    if (error instanceof SquareCloudBlobError) {
        if (error.isUpgradeRequired()) {
            console.error(error.message); // your plan lacks this feature or limit
        } else if (error.code === "OBJECT_NOT_FOUND") {
            // ...
        } else {
            console.error(error.status, error.code, error.extra);
        }
    } else {
        throw error; // network error or file error, see below
    }
}
```

### O que não é um `SquareCloudBlobError`

* **Erros de rede não são encapsulados.** Quando uma requisição não recebe uma resposta completa (falha de DNS, conexão reiniciada, um corpo cortado no meio da leitura), o erro original do `fetch` é lançado como está, após eventuais [novas tentativas](#política-de-novas-tentativas).
* **Erros de arquivo.** No Node.js, um caminho de `put()` que não pode ser aberto lança um `Error` simples (`Cannot open file: <path>`, erro original em `cause`). No navegador, um caminho falha com o erro da importação de `node:fs`.
* **Um `@aws-sdk/client-s3` ausente.** [`s3()`](/pt-br/sdks/blob/s3) lança o erro de importação do módulo.

### `UNKNOWN_ERROR`

`UNKNOWN_ERROR` é o **único código que o próprio SDK cria**. Ele é usado quando a resposta não tem código de erro: um corpo que não é JSON (uma página de erro de proxy, por exemplo) ou uma resposta `2xx` sem `status: "success"`. `status` continua contendo o status HTTP real.

### Falhas por objeto

As operações em lote informam as falhas no resultado em vez de lançar erro:

* [`update()`](/pt-br/sdks/blob/objects#atualizando-objetos): cada resultado tem `ok: false` e um `code`.
* [`delete([ids])`](/pt-br/sdks/blob/objects#excluindo): objetos inexistentes vão para `not_found`, outras falhas para `failed`.

## Códigos de erro

`BlobErrorCode` é a lista de códigos própria da API de Blob Storage. **Não** é a mesma lista de códigos de erro da API principal da Square Cloud. Para o status HTTP e o significado de cada código, veja a [referência de erros da API de Blob](/pt-br/blob-reference/errors).

<AccordionGroup>
  <Accordion title="Globais">
    `ACCESS_DENIED`, `RATE_LIMITED`, `MISSING_SCOPE`, `RESOURCE_NOT_ALLOWED`, `UPLOAD_TOKEN_NOT_ALLOWED`, `UPLOAD_TOKEN_USED`, `PREFIX_NOT_ALLOWED`, `PERMISSION_DENIED`, `ACCOUNT_BLOCKED`, `UPGRADE_REQUIRED`, `STORAGE_QUOTA_EXCEEDED`, `PRIVATE_STORAGE_UNAVAILABLE`, `PUBLIC_STORAGE_UNAVAILABLE`, `TOO_MANY_CONCURRENT_UPLOADS`, `UPLOAD_FAILED`, `INTERNAL_SERVER_ERROR`, `NOT_FOUND`

    `RATE_LIMIT` está **depreciado**: o serviço não o envia mais (veja `RATE_LIMITED`), mas ele continua no tipo.
  </Accordion>

  <Accordion title="Objetos">
    `OBJECT_NOT_FOUND`, `OBJECT_ALREADY_EXISTS`, `OBJECT_IS_LEGACY`, `CHECKSUM_MISMATCH`, `INVALID_CONTENT_TYPE`, `FILE_TOO_LARGE`, `FILE_TOO_SMALL`, `BLOCKED_FILE_TYPE`, `INVALID_FILE_TYPE`, `FILE_TYPE_NOT_ALLOWED`, `NOTHING_TO_UPDATE`, `VISIBILITY_CHANGE_FAILED`, `UPDATE_FAILED`, `DELETE_FAILED`, `TOO_MANY_OBJECTS`, `SAME_OBJECT`, `INVALID_DESTINATION`, `COPY_FAILED`, `PREFIX_REQUIRED`, `INVALID_CONTINUATION_TOKEN`
  </Accordion>

  <Accordion title="Uploads multipart (em partes)">
    `TOO_MANY_CONCURRENT_CHUNKS`, `TOO_MANY_OPEN_UPLOADS`, `INVALID_UPLOAD_TOKEN`, `UPLOAD_NOT_FOUND`, `NO_CHUNKS_UPLOADED`, `EMPTY_CHUNK`, `INVALID_CHUNK_PART`, `CHUNK_TOO_SMALL`, `CHUNK_TOO_LARGE`
  </Accordion>

  <Accordion title="Regras, tokens de upload, compartilhamentos e S3">
    `TOO_MANY_RULES`, `DUPLICATE_RULE_PREFIX`, `INVALID_RULES`, `UPLOAD_TOKEN_TOO_LARGE`, `TOO_MANY_SHARES`, `SHARE_NOT_FOUND`, `INVALID_SHARE`, `API_KEY_REQUIRED`, `LEGACY_API_KEY`
  </Accordion>

  <Accordion title="Validação (400)">
    Qualquer código `INVALID_*`, como `INVALID_OBJECT`, `INVALID_OBJECT_NAME` ou `INVALID_RULE_PREFIX`. Os erros de regras trazem o `prefix` problemático em `error.extra`.
  </Accordion>

  <Accordion title="SDK">
    `UNKNOWN_ERROR`: a resposta não tinha código de erro (veja [acima](#unknown_error)).
  </Accordion>
</AccordionGroup>

`BlobErrorCode` também aceita qualquer outra string, então um código que o serviço adicionar no futuro continua passando na checagem de tipos.

## Política de novas tentativas

O SDK só tenta novamente o que é **seguro repetir**: chamadas `GET` e **partes** de uploads multipart (cada número de parte pode ser enviado de novo).

| Repetido                             | Chamadas                                                                                                                                                                                           |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Sim**, até `maxRetries` (padrão 2) | `list()`, `listPage()`, `info()`, `downloadUrl()`, `stats()`, `rules.get()`, `shares.list()`, `s3Credentials()` e cada parte de um `put()` multipart                                               |
| **Não**, tentativa única             | `put()` simples, início, conclusão e cancelamento de um upload multipart, `update()`, `copy()`, `move()`, `delete()`, `rules.set()`, `uploadTokens.create()`, `shares.create()`, `shares.revoke()` |

Uma chamada repetível é tentada novamente em caso de:

* um **erro de rede** (incluindo um corpo cortado no meio da leitura);
* **qualquer resposta `5xx`**;
* `TOO_MANY_CONCURRENT_CHUNKS` em uma parte de multipart: o servidor recusa a parte antes de lê-la, então ela é enviada novamente dentro do mesmo limite de tentativas.

Ela **nunca** é repetida em qualquer outro `4xx`, **incluindo `429`**. `RATE_LIMITED` pode ser um bloqueio da conta que dura cerca de 30 minutos, então o SDK deixa a decisão com você.

### Backoff

Antes da nova tentativa `n` (começando em 0), o SDK espera:

```text theme={"system"}
min(8 s, 500 ms · 2^n) · U(0.5, 1)
```

Ou seja, backoff exponencial limitado a 8 segundos, com jitter entre 50 % e 100 % do atraso. Com o padrão `maxRetries: 2`, uma chamada faz no máximo 3 tentativas.

### Repetindo escritas por conta própria

Uma escrita que falha com um erro de rede ou um `5xx` pode ou não ter sido aplicada. Repita-a apenas quando for seguro para você, por exemplo um `put()` com o mesmo `name` e `overwrite: true`.

```typescript theme={"system"}
import { SquareCloudBlobError } from "@squarecloud/blob";

async function putWithRetry(file, options, attempts = 3) {
    for (let i = 0; ; i++) {
        try {
            return await blob.put(file, { ...options, overwrite: true });
        } catch (error) {
            // fetch network errors are TypeErrors; 5xx are SquareCloudBlobErrors
            const retryable =
                error instanceof SquareCloudBlobError
                    ? error.status >= 500
                    : error instanceof TypeError;
            if (!retryable || i + 1 >= attempts) throw error;
            await new Promise((r) => setTimeout(r, 1000 * 2 ** i));
        }
    }
}
```

<Warning>
  Não repita `429 RATE_LIMITED` em um loop apertado: ultrapassar o limite da conta pode bloqueá-la por cerca de 30 minutos. Veja a [referência de erros da API de Blob](/pt-br/blob-reference/errors).
</Warning>

### Timeouts

Não há timeout no cliente nem forma de cancelar uma chamada: uma requisição dura o tempo que o `fetch` esperar.
