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

# Manejo de errores

> Códigos de error del SDK y patrones de manejo

El SDK lanza instancias de `NippyError` para errores operacionales. Usa `NippyErrorCodes` para manejar cada caso de forma explícita.

<Warning>
  No muestres mensajes internos de error directamente al usuario. Registra `error.code`, `error.status` y `error.traceId` para diagnóstico.
</Warning>

## Patrón base

```typescript theme={null}
import { NippyError, NippyErrorCodes } from '@nippy/sdk'

try {
  await nippy.spin({ userId, campaignId })
} catch (error) {
  if (!(error instanceof NippyError)) throw error

  console.error(error.code, error.message, error.traceId)
}
```

## Códigos de error

<AccordionGroup>
  <Accordion title="COOLDOWN_ACTIVE">
    **Causa:** El usuario giró recientemente y el cooldown de la campaña sigue activo.

    **Solución:** Consulta `getState()` y muestra `nextEligibleAt`.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.COOLDOWN_ACTIVE) {
      const state = await nippy.getState({ userId, campaignId })
      return { reason: 'cooldown', nextEligibleAt: state.nextEligibleAt }
    }
    ```
  </Accordion>

  <Accordion title="SPIN_LIMIT_REACHED">
    **Causa:** El usuario agotó sus spins permitidos en la campaña.

    **Solución:** Deshabilita el botón de girar y muestra el estado actual.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.SPIN_LIMIT_REACHED) {
      return { reason: 'spin_limit_reached' }
    }
    ```
  </Accordion>

  <Accordion title="CAMPAIGN_NOT_FOUND">
    **Causa:** El `campaignId` no existe, no pertenece al negocio o la campaña está inactiva.

    **Solución:** Verifica el ID de campaña y su estado antes de exponerla en tu app.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.CAMPAIGN_NOT_FOUND) {
      return { reason: 'campaign_unavailable' }
    }
    ```
  </Accordion>

  <Accordion title="ALREADY_CLAIMED">
    **Causa:** Se llamó `claim()` para un premio que ya fue reclamado.

    **Solución:** Trata el caso como idempotente y muestra el premio ya reclamado.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.ALREADY_CLAIMED) {
      return { reason: 'already_claimed' }
    }
    ```
  </Accordion>

  <Accordion title="RESERVATION_EXPIRED">
    **Causa:** El usuario no reclamó el premio antes de la expiración de la reserva.

    **Solución:** Informa que el tiempo expiró y vuelve a consultar `getState()`.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.RESERVATION_EXPIRED) {
      const state = await nippy.getState({ userId, campaignId })
      return { reason: 'reservation_expired', state }
    }
    ```
  </Accordion>

  <Accordion title="UNAUTHORIZED">
    **Causa:** Falta la API key o la key es inválida.

    **Solución:** Revisa `NIPPY_API_KEY` y confirma que use el prefijo correcto.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.UNAUTHORIZED) {
      logger.error('Invalid Nippy API key')
    }
    ```
  </Accordion>

  <Accordion title="FORBIDDEN">
    **Causa:** La API key no tiene acceso al recurso solicitado.

    **Solución:** Revisa permisos y pertenencia del recurso en la consola.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.FORBIDDEN) {
      logger.error('Nippy key does not have access to this resource')
    }
    ```
  </Accordion>

  <Accordion title="INVALID_PARAMETERS">
    **Causa:** Faltan campos requeridos o algún valor tiene formato incorrecto.

    **Solución:** Valida los datos antes de llamar al SDK.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.INVALID_PARAMETERS) {
      return { reason: 'invalid_request' }
    }
    ```
  </Accordion>

  <Accordion title="SERVER_ERROR">
    **Causa:** Nippy respondió con un error 5xx después de los reintentos automáticos.

    **Solución:** Registra `traceId`, muestra un estado genérico y reintenta más tarde.

    ```typescript theme={null}
    if (error.code === NippyErrorCodes.SERVER_ERROR) {
      logger.error('Nippy server error', { traceId: error.traceId })
      return { reason: 'temporary_error' }
    }
    ```
  </Accordion>
</AccordionGroup>

## Propiedades de NippyError

```typescript theme={null}
error.code      // string
error.message   // string
error.status    // number
error.traceId   // string | undefined
```
