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

# Errores y reintentos

> SquareCloudBlobError, la lista BlobErrorCode, los errores de red que no se envuelven y exactamente qué llamadas reintenta @squarecloud/blob.

## `SquareCloudBlobError`

Todo fallo de la API lanza un `SquareCloudBlobError`.

| Propiedad             | Tipo                      | Descripción                                                                                                                        |
| --------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `status`              | `number`                  | Estado HTTP de la respuesta.                                                                                                       |
| `code`                | `BlobErrorCode`           | El código de error de la API, p. ej. `OBJECT_NOT_FOUND`.                                                                           |
| `message`             | `string`                  | La explicación del servidor, o el código cuando no hay ninguna.                                                                    |
| `extra`               | `Record<string, unknown>` | Todos los demás campos del cuerpo del error, p. ej. `prefix` en los errores de reglas.                                             |
| `isUpgradeRequired()` | `() => boolean`           | `true` para `UPGRADE_REQUIRED`, el código de todos los rechazos por plan (límite, funcionalidad o plan). El `message` indica cuál. |

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

### Lo que no es un `SquareCloudBlobError`

* **Los errores de red no se envuelven.** Cuando una petición no recibe una respuesta completa (fallo de DNS, conexión reiniciada, un cuerpo cortado a mitad de lectura), el error original de `fetch` se lanza tal cual, después de los posibles [reintentos](#política-de-reintentos).
* **Errores de archivo.** En Node.js, una ruta de `put()` que no se puede abrir lanza un `Error` simple (`Cannot open file: <path>`, con el error original en `cause`). En un navegador, una ruta falla con el error de importar `node:fs`.
* **La falta de `@aws-sdk/client-s3`.** [`s3()`](/es/sdks/blob/s3) lanza el error de importación del módulo.

### `UNKNOWN_ERROR`

`UNKNOWN_ERROR` es el **único código que crea el propio SDK**. Se usa cuando la respuesta no tiene código de error: un cuerpo que no es JSON (la página de error de un proxy, por ejemplo) o una respuesta `2xx` sin `status: "success"`. `status` sigue conteniendo el estado HTTP real.

### Fallos por objeto

Las operaciones por lotes indican los fallos en su resultado en lugar de lanzar un error:

* [`update()`](/es/sdks/blob/objects#actualizar-objetos): cada resultado tiene `ok: false` y un `code`.
* [`delete([ids])`](/es/sdks/blob/objects#eliminar): los objetos inexistentes van a `not_found`, y los demás fallos a `failed`.

## Códigos de error

`BlobErrorCode` es la lista de códigos propia de la API de Blob Storage. **No** es la misma lista que la de los códigos de error de la API principal de Square Cloud. Para el estado HTTP y el significado de cada código, consulta la [referencia de errores de la API de Blob](/es/blob-reference/errors).

<AccordionGroup>
  <Accordion title="Globales">
    `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á **obsoleto**: el servicio ya no lo envía (consulta `RATE_LIMITED`), pero sigue en el 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="Subidas multipart (por 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="Reglas, tokens de subida, enlaces compartidos y 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="Validación (400)">
    Cualquier código `INVALID_*`, como `INVALID_OBJECT`, `INVALID_OBJECT_NAME` o `INVALID_RULE_PREFIX`. Los errores de reglas llevan el `prefix` problemático en `error.extra`.
  </Accordion>

  <Accordion title="SDK">
    `UNKNOWN_ERROR`: la respuesta no tenía código de error (consulta [más arriba](#unknown_error)).
  </Accordion>
</AccordionGroup>

`BlobErrorCode` también acepta cualquier otro string, de modo que un código que el servicio añada más adelante sigue pasando la comprobación de tipos.

## Política de reintentos

El SDK solo reintenta lo que es **seguro repetir**: las llamadas `GET` y las **partes** de las subidas multipart (cada número de parte se puede volver a enviar).

| Se reintenta                               | Llamadas                                                                                                                                                                                                 |
| ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Sí**, hasta `maxRetries` (por defecto 2) | `list()`, `listPage()`, `info()`, `downloadUrl()`, `stats()`, `rules.get()`, `shares.list()`, `s3Credentials()` y cada parte de un `put()` multipart                                                     |
| **No**, un único intento                   | `put()` simple, el inicio, la finalización y el aborto de una subida multipart, `update()`, `copy()`, `move()`, `delete()`, `rules.set()`, `uploadTokens.create()`, `shares.create()`, `shares.revoke()` |

Una llamada reintentable se reintenta ante:

* un **error de red** (incluido un cuerpo cortado a mitad de lectura);
* **cualquier respuesta `5xx`**;
* `TOO_MANY_CONCURRENT_CHUNKS` en una parte multipart: el servidor rechaza la parte antes de leerla, así que se vuelve a enviar dentro del mismo presupuesto.

**Nunca** se reintenta ante cualquier otro `4xx`, **incluido el `429`**. `RATE_LIMITED` puede ser un bloqueo de la cuenta que dura unos 30 minutos, así que el SDK deja la decisión en tus manos.

### Backoff

Antes del reintento `n` (empezando en 0), el SDK espera:

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

Es decir, backoff exponencial con un máximo de 8 segundos, con un jitter de entre el 50 % y el 100 % del retardo. Con el valor por defecto `maxRetries: 2`, una llamada hace como máximo 3 intentos.

### Reintentar escrituras por tu cuenta

Una escritura que falla con un error de red o un `5xx` puede haberse aplicado o no. Reinténtala solo cuando repetirla sea seguro para ti, por ejemplo un `put()` al mismo `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>
  No reintentes un `429 RATE_LIMITED` en un bucle cerrado: superar el presupuesto de toda la cuenta puede bloquear la cuenta durante unos 30 minutos. Consulta la [referencia de errores de la API de Blob](/es/blob-reference/errors).
</Warning>

### Timeouts

No hay timeout en el cliente ni forma de cancelar una llamada: una petición dura lo que espere `fetch`.
