Ir al contenido

Errores y reintentos del SDK

Los métodos rechazan su promesa ante un error. Distingue los errores de API, transporte y validación para decidir qué hacer después.

import {
createFactuCatSdk,
FactuCatApiError,
FactuCatNetworkError,
} from '@factucat/sdk'
import { z } from 'zod'
const factucat = createFactuCatSdk({
apiKey: process.env.FACTUCAT_API_KEY!,
})
try {
const cuenta = await factucat.getMe()
console.log(cuenta.scopes)
} catch (error) {
if (error instanceof FactuCatApiError) {
console.error({
code: error.code,
status: error.status,
requestId: error.requestId,
})
} else if (error instanceof FactuCatNetworkError) {
console.error({
method: error.method,
path: error.path,
timedOut: error.timedOut,
})
} else if (error instanceof z.ZodError) {
console.error(error.issues.map(({ path, message }) => ({ path, message })))
} else {
throw error
}
}

El ejemplo usa Zod para reconocer errores de validación. Si lo importas en tu aplicación, declara zod como dependencia directa. No se exporta ZodError desde @factucat/sdk.

Indica una respuesta HTTP de error. Es una subclase de Error exportada por el SDK.

Propiedad Tipo Significado
name string FactuCatApiError.
message string Mensaje devuelto por la API.
code PublicApiErrorCode Código estable de error.
status number Estado HTTP.
requestId string Identificador para investigar la solicitud.
retryable boolean Indica si el servidor considera reintentable el error; el SDK no lo reintenta automáticamente.

Si la respuesta HTTP de error no cumple el contrato, el SDK usa code: 'internal_error', requestId: 'unknown' y conserva el estado HTTP. En ese caso, retryable es true para estados 500 o superiores.

Código Qué revisar
bad_request, invalid_json, validation_error Argumentos, JSON o validaciones de negocio.
missing_api_key, invalid_api_key Llave, ambiente, revocación y autenticación.
missing_scope Permisos de la API key.
plan_required Plan Free, Miau o Miau legacy: activa Miau Pro o FactuCat API.
not_found Recurso inexistente, ajeno a la cuenta o no disponible en ese estado.
method_not_allowed Método HTTP no admitido.
conflict Estado del recurso incompatible con la operación.
idempotency_conflict La clave ya se usó con otro contenido.
idempotency_in_progress La solicitud con esa clave sigue en curso.
missing_idempotency_key Código reconocido por el contrato; las mutaciones actuales admiten omitir la clave.
rate_limit_exceeded Límite de solicitudes alcanzado.
pac_unavailable El PAC no responde temporalmente (HTTP 503, retryable: true). Reintenta más tarde con la misma clave de idempotencia.
internal_error Falla interna o respuesta HTTP de error inválida.

En producción, GET /me y las demás operaciones autenticadas responden 403 plan_required cuando el plan es Free, Miau o Miau legacy. Esos planes no habilitan la API: necesitas Miau Pro o FactuCat API. En sandbox, una llave fc_test_... no exige plan de pago.

No hay un endpoint público para subir de plan, abrir Checkout ni aplicar cupones. Activa el plan en la webapp, en Configuración → Suscripción, y completa el Checkout de Stripe. El consumo del plan API se explica en Consumo y facturación.

Un 409, 429, 500 o 503 se entrega a tu aplicación sin un segundo intento automático. FactuCatApiError no expone los headers HTTP, incluido Retry-After. Para leerlos, utiliza el transporte personalizado.

Indica que no se pudo completar la solicitud por un problema de transporte o una cancelación local.

Propiedad Tipo Significado
name string FactuCatNetworkError.
message string Descripción del fallo.
method 'GET' | 'POST' | 'PATCH' | 'DELETE' Método HTTP de la solicitud.
path string Ruta solicitada, incluyendo los filtros de consulta si existen.
retryable boolean El SDK lo establece en true; no implica que repetir una operación nueva sea seguro.
timedOut boolean El error final tenía nombre AbortError. También puede ocurrir al cancelar manualmente con AbortController.
cause unknown Error original, si está disponible.

Para distinguir una cancelación iniciada por tu aplicación, conserva el signal y revisa su propiedad aborted. No interpretes timedOut como evidencia de que el servidor rechazó la operación.

Un ZodError puede producirse antes de enviar una solicitud, por sus argumentos, o después de recibir una respuesta exitosa que no cumple el contrato. El SDK no reintenta estos errores.

La validación local comprueba la forma de los datos. Las reglas fiscales, la pertenencia de recursos, los permisos y el estado del documento se validan en el servidor.

Situación Comportamiento automático
Fallo de red o timeout Un reintento, con una espera de 250 ms.
Mutación que se reintenta Misma clave de idempotencia y contenido.
Consulta GET Se puede reintentar; no genera clave.
Error HTTP o de validación No se reintenta.
signal cancelado Se interrumpe la espera; no se inicia un reintento si el signal ya estaba cancelado al decidirlo.

El timeout predeterminado es de 30 segundos por intento. La cancelación de la espera no deshace una operación que el servidor ya recibió.

Guarda el ID del borrador y tu clave de timbrado antes de llamar a stampDraft(). Si se pierde la respuesta, consulta getInvoice() con ese ID. No crees otro borrador para evadir el error.

La clave generada automáticamente solo se conserva dentro de una llamada del SDK. Para recuperarte desde otro proceso o después de un reinicio, utiliza tu propia clave persistida. Idempotencia y recuperación.