Saltar al contenido principal

Errores

Todas las respuestas siguen la misma forma:

Éxito
{ "ok": true, "result": { } }
Error
{ "ok": false, "error": "Mensaje explicativo", "code": "VALIDATION_ERROR" }

Chequeá ok, no el status HTTP. code acompaña a los errores de negocio; los de infraestructura (límite de peticiones, timeout) traen sólo error. Algunos errores de validación agregan details con el detalle campo por campo.

Tabla completa

HTTPcodeCuándo aparece¿Reintentar?
400VALIDATION_ERRORPayload inválido, punto de venta inexistente, faltan fechas de servicioNo — corregí el pedido
401Falta el Authorization, clave inválida o revocada, ruta no habilitadaNo
402SUBSCRIPTION_EXPIREDEl período contratado de la empresa vencióRecién al regularizar el pago
404NOT_FOUNDEl comprobante o el punto de venta no existe, o el documento no está en el padrón de ARCANo
409VALIDATION_ERRORClave de idempotencia reusada para otro comprobanteNo — generá una clave nueva
409PDF_NOT_READYEl PDF todavía se está generando, en unos segundos
422ARCA_ERRORARCA rechazó el comprobanteNo — corregí el pedido
429Límite de peticiones, con espera
429VOUCHER_LOCK_TIMEOUTOtra emisión del mismo punto de venta sigue en curso, ver Retry-After
429QUOTA_EXCEEDEDSe agotó la cuota de una operación administrativa, pasada la ventana
429SUBSCRIPTION_QUOTA_EXCEEDEDSe agotó la cuota mensual de comprobantesRecién al ampliar el límite o al renovarse el período
500Error interno, con backoff
502ARCA_CONNECTION_ERRORNo se pudo hablar con los servidores de ARCA, con backoff — salvo que sea el certificado sin delegar
504Se agotó el tiempo del pedido, con la misma idempotency

Los que importan

422 ARCA_ERROR — ARCA rechazó el comprobante

Es un rechazo de negocio: el comprobante no se guardó y no consumió numeración.

{
"ok": false,
"error": "(10015) Factura B con importe total mayor a $ … requiere identificación del comprador",
"code": "ARCA_ERROR",
"details": [{ "code": 10015, "msg": "Factura B con importe total mayor a …" }]
}

details trae el código y el mensaje exactos de ARCA. Registralos: son la única forma de diagnosticar qué regla se violó.

Reintentar sin cambiar nada va a fallar igual. Los motivos más comunes:

CódigoQué significaCómo se corrige
10015Factura B/C sobre el umbral sin identificar al compradorPedile DNI o CUIT al cliente
Documento inválido para el tipo de comprobanteFactura A exige CUIT; ver qué comprobante emitir
Fecha fuera del rango permitidoARCA acota cuánto podés retroceder o adelantar la fecha
Punto de venta no habilitadoTiene que ser de tipo webservice; ver puntos de venta

504 — se agotó el tiempo

Un 504 no significa que el comprobante no se emitió

Puede haberse emitido y el corte haber ocurrido mientras volvía la respuesta. Reintentá con la misma idempotency: si ya existía, lo recuperás con idempotencyHit: true; si no, se emite ahora. Nunca se duplica.

Es exactamente el problema para el que existe la clave de idempotencia. Generar una clave nueva en el reintento sí puede duplicar el comprobante.

429 VOUCHER_LOCK_TIMEOUT — otra emisión en curso

ARCA exige numeración consecutiva, así que se emite de a un comprobante por vez para cada combinación de punto de venta y tipo. Si llega un pedido mientras otro se autoriza, espera su turno solo. Este error aparece únicamente si pasados esos segundos la emisión anterior sigue en curso.

Es transitorio y seguro de reintentar: el comprobante no se emitió y el número quedó libre. Viene con el header Retry-After. Reintentá con la misma idempotency.

Si lo ves seguido, estás emitiendo en paralelo sobre el mismo punto de venta: secuenciá. Ver Límites.

409 — clave de idempotencia reusada

{
"ok": false,
"error": "La clave de idempotencia ya corresponde al comprobante 1-6-45, no al que se está pidiendo (2-6). Usá una clave distinta para cada comprobante.",
"code": "VALIDATION_ERROR"
}

La clave ya pertenece a un comprobante de otro punto de venta o de otro tipo. Es permanente: reintentar falla igual. Generá una clave nueva, y usá un UUID por comprobante.

402 SUBSCRIPTION_EXPIRED — período vencido

{
"ok": false,
"error": "El período contratado de la empresa venció. Regularizá el pago para volver a emitir comprobantes.",
"code": "SUBSCRIPTION_EXPIRED"
}

No es un problema de credenciales —la clave sigue siendo válida—, por eso responde 402 y no 401. No consume numeración. Se resuelve abonando la renovación en la app, en Administrar → Pagos.

429 SUBSCRIPTION_QUOTA_EXCEEDED — cuota mensual agotada

{
"ok": false,
"error": "Se agotó la cuota de 500 comprobantes de este período hasta el 2026-09-16. …",
"code": "SUBSCRIPTION_QUOTA_EXCEEDED",
"details": {
"quota": { "granted": 500, "used": 500, "remaining": 0, "periodEnd": "2026-09-16" }
}
}

La suscripción está al día: lo que se agotó es la capacidad del mes. Cede al ampliar el límite o al renovarse el período, así que no corresponde un backoff automático — reintentar antes de eso no cambia nada.

details.quota te deja distinguir los dos casos sin leer el mensaje:

Para no chocar de sorpresa: cada emisión devuelve quota.remaining, y al 90% del cupo la cuenta recibe un aviso por email.

502 ARCA_CONNECTION_ERROR — "Computador no autorizado a acceder al servicio"

{
"ok": false,
"error": "WSAA Fault: Computador no autorizado a acceder al servicio",
"code": "ARCA_CONNECTION_ERROR"
}

El certificado está cargado y activo, pero su alias no está delegado al servicio que se está usando. Cada servicio de ARCA se autoriza por separado:

Qué estabas haciendoServicio que hay que delegar
Emitir un comprobanteFacturación Electrónica (wsfe)
Consultar el padrón de una persona físicaConsulta a Padrón A13
Consultar el padrón de una persona jurídicaConstancia de Inscripción

Se resuelve en el portal de ARCA, en el Administrador de Relaciones de Clave Fiscal (en homologación, desde WSASS), asociando el alias del certificado al servicio que falta: Vincular tu certificado de ARCA → Paso 4.

Es un 502, pero no cede reintentando

Llega como error de conexión porque falla la autenticación contra ARCA, no la emisión. Reintentar agota los intentos y termina fallando igual: hay que hacer la delegación. Es la causa número uno de "tengo el certificado cargado y no puedo facturar".

GET /:id-empresa/arca/status te dice cuál de los servicios está fallando —conexión, autenticación y padrones se prueban por separado— y devuelve la sugerencia correspondiente. Ver consultas a ARCA.

Cómo manejarlos

Una regla simple que cubre todos los casos:

async function emitir(payload, intentos = 3) {
// La clave se genera UNA vez, fuera del bucle: es lo que hace que el
// reintento recupere el comprobante en vez de emitir otro.
const body = { ...payload, idempotency: payload.idempotency ?? crypto.randomUUID() }

for (let intento = 1; intento <= intentos; intento++) {
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) })
const data = await res.json()

if (data.ok) return data.result

// Errores permanentes: reintentar no cambia nada.
if ([400, 401, 402, 403, 404, 409, 422].includes(res.status)) {
throw new Error(`${data.code}: ${data.error}`)
}
// La cuota mensual tampoco cede reintentando.
if (data.code === 'SUBSCRIPTION_QUOTA_EXCEEDED') {
throw new Error(data.error)
}
// El resto (429, 500, 502, 504) es transitorio.
if (intento === intentos) throw new Error(data.error ?? 'Error tras varios intentos')

const retryAfter = Number(res.headers.get('Retry-After')) || 2 ** intento
await new Promise((r) => setTimeout(r, retryAfter * 1000))
}
}

Las tres decisiones que importan:

  1. La idempotency se genera una sola vez, fuera del bucle. Es lo único que hace seguro el reintento.
  2. Los errores permanentes no se reintentan. Un 422 reintentado tres veces sigue siendo un 422, y sólo suma latencia.
  3. Respetá Retry-After cuando venga; si no, backoff exponencial.

Implementaciones completas con esta lógica en JavaScript, PHP y Python: Ejemplos.