Sandbox sobre la preproducción de la AEAT · sin tarjeta · Primera factura en 5 minutos
verifactu.co

Cadena · Concurrencia

La cadena de huellas: por qué se bifurca

Cada huella incluye la del registro anterior del mismo emisor. Eso la hace verificable — y la hace frágil ante la concurrencia, de una manera que la AEAT no te va a avisar.

¿Qué es la cadena de huellas de VeriFactu y cómo se rompe?

Es el encadenamiento de los registros de un mismo emisor: la huella de cada uno incluye la del anterior. Se rompe cuando dos facturas del mismo emisor se registran a la vez y ambas se encadenan al mismo registro previo.

La AEAT acepta las dos sin dar ningún error, y como la huella es irreversible no se puede corregir después. La única solución es serializar el registro por emisor, tomando el cerrojo antes de leer la última huella y soltándolo después de persistir la nueva.

Fuente: Orden HAC/1177/2024, de 17 de octubre · Real Decreto 1007/2023, de 5 de diciembre

01 Qué es la cadena Y qué la rompe

Cada registro incluye en su huella la huella del registro anterior del mismo emisor. Eso convierte la secuencia en una cadena: alterar un registro pasado invalidaría todos los posteriores, y por eso el reglamento la exige.

01

Es por emisor, no global

Cada NIF tiene su propia cadena, independiente del resto. Dos emisores pueden registrar a la vez sin problema; el mismo emisor, no.

02

El primer registro lleva la huella vacía

En la cadena literal aparece Huella= — el campo existe, con valor vacío. Omitirlo daría otra cadena y por tanto otra huella.

03

Una anulación entra en la cadena

No borra: encadena un registro nuevo, con sus propios campos y su propia huella. Cómo se anula.

04

Un rechazo NO entra

Si la AEAT rechaza un registro, no forma parte de la cadena: el siguiente se encadena al último aceptado.

02 La bifurcación El fallo que no da error

Dos facturas a la vez y la cadena deja de ser una cadena.

Cómo ocurre
# Dos procesos, el mismo emisor, el mismo instante.

Proceso A                          Proceso B
─────────                          ─────────
lee última huella  → A91C…E4
                                   lee última huella  → A91C…E4
calcula F-0184
  Huella=A91C…E4
                                   calcula F-0185
                                     Huella=A91C…E4   ← el MISMO anterior
remite  → aceptado
                                   remite  → aceptado

# La AEAT acepta las dos. No hay error, no hay aviso.
# La cadena ya no es una cadena: es un árbol.
# Y la huella es irreversible.
Esto no es teórico. Nos pasó en producción en un SaaS de alquiler de vehículos con picos de entrega simultánea, y es uno de los dos fallos que ya no se podían deshacer cuando se detectaron. El caso.
03 Cómo se evita Serializar por emisor
El cerrojo
// Lo que hay que hacer: un cerrojo POR EMISOR,
// tomado ANTES de leer la última huella y soltado
// DESPUÉS de persistir la nueva.

BEGIN;

-- Bloquea la fila del emisor, no la tabla entera:
-- dos emisores distintos deben poder registrar a la vez.
SELECT ultima_huella
  FROM emisores
 WHERE nif = 'B12345678'
   FOR UPDATE;

-- calcular la huella con esa «anterior»
INSERT INTO registros (...) VALUES (...);

UPDATE emisores
   SET ultima_huella = '<la nueva>'
 WHERE nif = 'B12345678';

COMMIT;

// El cerrojo se suelta al COMMIT, no antes. Soltarlo
// tras leer y antes de escribir deja exactamente la
// misma ventana de bifurcación que no tenerlo.
01

Un cerrojo por emisor, no global

Bloquear la tabla entera funciona y mata el rendimiento: dos emisores distintos no compiten por nada.

02

Tomarlo ANTES de leer la última huella

Si lo tomas después de leer, ya has leído un valor que otro puede haber cambiado.

03

Soltarlo DESPUÉS de persistir la nueva

Soltarlo entre leer y escribir deja exactamente la misma ventana que no tener cerrojo.

04

Y por eso la remisión es asíncrona

Serializar por emisor obliga a encolar. Una API que prometa registrar de forma síncrona y paralela para el mismo emisor está prometiendo algo incompatible con el reglamento.

Es la razón de que no te dejemos calcular la huella tú y mandárnosla. La huella depende de un estado —el último registro de ese emisor— y si dos procesos tuyos lo leen a la vez, la bifurcación deja de ser evitable por nuestra parte. Cómo se calcula la huella.
FAQ Preguntas Respuestas directas
¿Qué es la cadena de huellas en VeriFactu?

Es el encadenamiento de los registros de facturación de un mismo emisor: la huella de cada registro incluye la huella del registro anterior. Así, alterar un registro pasado invalidaría todos los posteriores.

¿Qué pasa si dos facturas del mismo emisor se registran a la vez?

Que las dos pueden leer el mismo «registro anterior» y encadenarse a él. La cadena se bifurca, la AEAT acepta ambas sin dar ningún error, y como la huella es irreversible ya no se puede corregir. Hay que serializar por emisor.

¿La cadena es por emisor o para toda la cuenta?

Por emisor. Cada NIF tiene su propia cadena independiente, así que dos emisores distintos pueden registrar simultáneamente sin ningún riesgo.

¿Un registro rechazado rompe la cadena?

No. Un registro rechazado no entra en la cadena: el siguiente se encadena al último aceptado. Lo que sí hay que resolver es el dato que provocó el rechazo.

¿Se puede reparar una cadena bifurcada?

No de forma útil. Podrías recalcular las huellas, pero los registros ya están remitidos a la AEAT con las incorrectas. Rehacerlo implicaría reenviar el histórico completo.

Última revisión normativa: Especificaciones de huella AEAT v0.1.2 Revisado por el equipo técnico de verifactu.co