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

# Errori e retry

> SquareCloudBlobError, l'elenco BlobErrorCode, gli errori di rete che non vengono incapsulati ed esattamente quali chiamate @squarecloud/blob ripete.

## `SquareCloudBlobError`

Ogni errore dell'API lancia un `SquareCloudBlobError`.

| Proprietà             | Tipo                      | Descrizione                                                                                                                         |
| --------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `status`              | `number`                  | Status HTTP della risposta.                                                                                                         |
| `code`                | `BlobErrorCode`           | Il codice di errore dell'API, ad es. `OBJECT_NOT_FOUND`.                                                                            |
| `message`             | `string`                  | La spiegazione del server, oppure il codice quando non ce n'è una.                                                                  |
| `extra`               | `Record<string, unknown>` | Ogni altro campo del body dell'errore, ad es. `prefix` negli errori delle regole.                                                   |
| `isUpgradeRequired()` | `() => boolean`           | `true` per `UPGRADE_REQUIRED`, il codice di ogni rifiuto legato al piano (limite, funzionalità o piano). Il `message` indica quale. |

```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
    }
}
```

### Cosa non è un `SquareCloudBlobError`

* **Gli errori di rete non vengono incapsulati.** Quando una richiesta non riceve una risposta completa (errore DNS, connessione reimpostata, body troncato durante la lettura), l'errore originale di `fetch` viene lanciato così com'è, dopo eventuali [retry](#politica-di-retry).
* **Errori dei file.** In Node.js, un percorso di `put()` che non può essere aperto lancia un semplice `Error` (`Cannot open file: <path>`, errore originale in `cause`). In un browser, un percorso fallisce con l'errore dell'importazione di `node:fs`.
* **Un `@aws-sdk/client-s3` mancante.** [`s3()`](/it/sdks/blob/s3) lancia l'errore di importazione del modulo.

### `UNKNOWN_ERROR`

`UNKNOWN_ERROR` è l'**unico codice creato dall'SDK stesso**. Viene usato quando la risposta non ha un codice di errore: un body non JSON (ad esempio la pagina di errore di un proxy) o una risposta `2xx` senza `status: "success"`. `status` contiene comunque lo status HTTP reale.

### Fallimenti per singolo oggetto

Le operazioni batch riportano i fallimenti nel loro risultato invece di lanciare errori:

* [`update()`](/it/sdks/blob/objects#aggiornare-gli-oggetti): ogni risultato ha `ok: false` e un `code`.
* [`delete([ids])`](/it/sdks/blob/objects#eliminare): gli oggetti mancanti finiscono in `not_found`, gli altri fallimenti in `failed`.

## Codici di errore

`BlobErrorCode` è l'elenco di codici proprio dell'API di Blob Storage. **Non** è lo stesso elenco dei codici di errore dell'API principale di Square Cloud. Per lo status HTTP e il significato di ogni codice, vedi il [riferimento degli errori dell'API Blob](/it/blob-reference/errors).

<AccordionGroup>
  <Accordion title="Globali">
    `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` è **deprecato**: il servizio non lo invia più (vedi `RATE_LIMITED`), ma resta nel tipo.
  </Accordion>

  <Accordion title="Oggetti">
    `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="Upload multipart (a blocchi)">
    `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="Regole, token di upload, condivisioni 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="Validazione (400)">
    Qualsiasi codice `INVALID_*`, come `INVALID_OBJECT`, `INVALID_OBJECT_NAME` o `INVALID_RULE_PREFIX`. Gli errori delle regole riportano il `prefix` responsabile in `error.extra`.
  </Accordion>

  <Accordion title="SDK">
    `UNKNOWN_ERROR`: la risposta non aveva un codice di errore (vedi [sopra](#unknown_error)).
  </Accordion>
</AccordionGroup>

`BlobErrorCode` accetta anche qualsiasi altra stringa, così un codice aggiunto in futuro dal servizio supera comunque il controllo dei tipi.

## Politica di retry

L'SDK ripete solo ciò che è **sicuro ripetere**: le chiamate `GET` e le **parti** degli upload multipart (ogni numero di parte può essere inviato di nuovo).

| Ripetuto                                    | Chiamate                                                                                                                                                                                               |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Sì**, fino a `maxRetries` (predefinito 2) | `list()`, `listPage()`, `info()`, `downloadUrl()`, `stats()`, `rules.get()`, `shares.list()`, `s3Credentials()`, e ogni parte di un `put()` multipart                                                  |
| **No**, un solo tentativo                   | `put()` semplice, avvio, completamento e annullamento di un upload multipart, `update()`, `copy()`, `move()`, `delete()`, `rules.set()`, `uploadTokens.create()`, `shares.create()`, `shares.revoke()` |

Una chiamata ripetibile viene ripetuta in caso di:

* un **errore di rete** (incluso un body troncato durante la lettura);
* **qualsiasi risposta `5xx`**;
* `TOO_MANY_CONCURRENT_CHUNKS` su una parte multipart: il server rifiuta la parte prima di leggerla, quindi viene inviata di nuovo entro lo stesso budget.

**Non** viene mai ripetuta per qualsiasi altro `4xx`, **incluso `429`**. `RATE_LIMITED` può essere un blocco dell'account che dura circa 30 minuti, quindi l'SDK lascia la decisione a te.

### Backoff

Prima del retry `n` (a partire da 0), l'SDK attende:

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

Ovvero, un backoff esponenziale limitato a 8 secondi, con jitter tra il 50 % e il 100 % del ritardo. Con il valore predefinito `maxRetries: 2`, una chiamata effettua al massimo 3 tentativi.

### Ripetere tu le scritture

Una scrittura che fallisce con un errore di rete o un `5xx` potrebbe essere stata applicata oppure no. Ripetila solo quando per te è sicuro farlo, ad esempio un `put()` sullo stesso `name` con `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>
  Non ripetere `429 RATE_LIMITED` in un ciclo serrato: superare il budget dell'intero account può bloccare l'account per circa 30 minuti. Vedi il [riferimento degli errori dell'API Blob](/it/blob-reference/errors).
</Warning>

### Timeout

Non esiste un timeout del client né un modo per annullare una chiamata: una richiesta dura quanto `fetch` attende.
