Capítulo 9 Manejo de Errores

9.1 Modelo de Manejo de Errores

Una implementación de DTP MUST seguir un modelo de manejo de errores de tres etapas "detectar-notificar-recuperar":

  1. Detectar: identificar condiciones anómalas.
  2. Notificar: enviar información de error al peer o a la capa superior.
  3. Recuperar: tomar acciones de recuperación según el tipo de error.

Una implementación MUST NOT descartar silenciosamente marcos al detectar un error sin notificación.

9.2 Sistema de Códigos de Error

DTP MUST utilizar el siguiente sistema de códigos de error. Los códigos de error MUST ser enteros no negativos, divididos en ocho rangos por módulo funcional:

RangoCategoríaEstrategia de Manejo
1xxxErrores de procesamiento de marcosDescartar marco + notificar al emisor
2xxxErrores de cifradoDescartar marco + notificar al emisor + puede disparar re-negociación de claves
3xxxErrores de AgreementDescartar Fragment + notificar al emisor + puede disparar re-negociación
4xxxErrores de DAGRechazar Fragment + notificar al emisor, o almacenar en caché y esperar
5xxxErrores de SessionIntentar la recuperación de la Session + cerrar y notificar a la capa superior en caso de fallo
6xxxErrores de reanudaciónPausar el envío + notificar a la aplicación de capa superior
7xxxErrores de versiónEnviar notificación de versión incompatible + intentar la degradación
8xxxErrores de permisoRechazar la operación + notificar al solicitante

9.3 Definiciones de Códigos de Error

Una implementación MUST utilizar las siguientes definiciones normativas de códigos de error. MUST NOT utilizar códigos de error no listados. Cualquier extensión MUST definirse en una versión posterior de esta especificación.

9.3.1 Errores de Procesamiento de Marcos (1xxx)

CódigoNombreCondición de Disparo
1001FRAME_DESERIALIZATION_FAILEDLos datos binarios recibidos no pueden deserializarse en un LogicalFrame
1002FRAME_INVALID_FORMATLa estructura del LogicalFrame es inválida o faltan campos requeridos

9.3.2 Errores de Cifrado (2xxx)

CódigoNombreCondición de Disparo
2001DECRYPTION_FAILEDFalló el descifrado del Payload (clave incorrecta o datos corruptos)
2002KEY_NOT_READYEl intercambio de claves de CAP aún no se ha completado; se rechaza la transmisión de datos

9.3.3 Errores de Agreement (3xxx)

CódigoNombreCondición de Disparo
3001AGREEMENT_NOT_FOUNDEl Fragment referencia un Agreement_ID desconocido
3002AGREEMENT_EXPIREDEl Agreement referenciado ha expirado (excedido validityPeriod)
3003AGREEMENT_NEGOTIATION_FAILEDLa negociación no puede completarse (timeout, rechazo del peer a re-negociar, etc.)

9.3.4 Errores de DAG (4xxx)

CódigoNombreCondición de Disparo
4001DAG_CYCLE_DETECTEDAñadir el Fragment formaría un ciclo en el DAG
4002DAG_DEPENDENCY_UNRESOLVEDLas dependencias del Fragment no se resuelven dentro del timeout de caché

9.3.5 Errores de Session (5xxx)

CódigoNombreCondición de Disparo
5001SESSION_NOT_FOUNDEl Session_ID referenciado no existe
5002SESSION_TIMEOUTLa Session ha expirado debido a inactividad
5003SESSION_RESTORE_FAILEDFalló la restauración de la Session tras la reconexión

9.3.6 Errores de Reanudación (6xxx)

CódigoNombreCondición de Disparo
6001BUFFER_FULLLa caché de Fragments no acusados del emisor ha alcanzado su capacidad
6002RETRANSMISSION_TIMEOUTTimeout de retransmisión de Fragment sin acuse de recibo (contador de reintentos agotado)

9.3.7 Errores de Versión (7xxx)

CódigoNombreCondición de Disparo
7001VERSION_INCOMPATIBLELa versión del protocolo del marco recibido es superior a la versión soportada por esta implementación

9.3.8 Errores de Permiso (8xxx)

CódigoNombreCondición de Disparo
8001PERMISSION_DENIEDEl rol actual no tiene permitido realizar esta operación
8002OBSERVER_WRITE_DENIEDUn Observer intentó una operación de escritura (los Observers son de solo lectura)

9.4 Unicidad del Código de Error

Una implementación MUST garantizar la unicidad del código de error:

  1. Cada código de error MUST corresponder a un único tipo de error.
  2. Diferentes tipos de error MUST NOT compartir el mismo código de error.
  3. La implementación MUST NOT redefinir códigos de error ya asignados por esta especificación.

9.5 Mecanismo de Notificación de Errores

9.5.1 ErrorNotificationFrame

Las notificaciones de error MUST transmitirse mediante un ControlFrame, definido como sigue:

interface ErrorNotificationFrame {
  frameType: "control";
  controlType: "error_notification";
  errorCode: DTPErrorCode;
  errorMessage: string;
  relatedFrameId?: FragmentID;
  relatedAgreementId?: AgreementID;
  details?: Record<string, unknown>;
}
CampoRequisito Normativo
frameTypeMUST ser "control"
controlTypeMUST ser "error_notification"
errorCodeMUST ser uno de los códigos de error definidos en la Sección 9.3
errorMessageMUST ser una descripción de error legible por humanos. SHOULD utilizar un idioma comprensible para el peer
relatedFrameIdOPTIONAL. Cuando el error es disparado por un marco específico, MUST incluir el fragmentId de ese marco
relatedAgreementIdOPTIONAL. Cuando el error está relacionado con un Agreement específico, MUST incluir el Agreement_ID
detailsOPTIONAL. MAY incluir información adicional para depuración

9.5.2 Transporte de la Notificación de Error

Un ErrorNotificationFrame MUST transmitirse sobre el canal regular de LogicalFrame y MUST tener su Payload cifrado.

Si el propio error impide el cifrado (por ejemplo, el error KEY_NOT_READY), la implementación MAY devolver el error a través de un canal fuera de banda definido por la implementación, pero MUST NOT enviar el error en texto plano por el canal cifrado.

9.6 Flujos Clave de Manejo de Errores

9.6.1 Fallo de Deserialización (1001)

Cuando un LogicalFrame recibido no puede deserializarse, el receptor MUST:

  1. Descartar el marco.
  2. Enviar la notificación de error FRAME_DESERIALIZATION_FAILED.
  3. MUST NOT cerrar la Session debido a un fallo de deserialización.

9.6.2 Fallo de Descifrado (2001)

Cuando un Payload recibido no puede descifrarse, el receptor MUST:

  1. Descartar el marco.
  2. Enviar la notificación de error DECRYPTION_FAILED.
  3. Contar el número de fallos consecutivos de descifrado.
  4. Si los fallos consecutivos exceden un umbral (RECOMMENDED como 3), SHOULD disparar a CAP para re-negociar las claves.

9.6.3 Detección de Ciclo en DAG (4001)

Cuando se detecta un ciclo en el DAG:

  1. El receptor MUST rechazar el Fragment.
  2. MUST devolver el error DAG_CYCLE_DETECTED.
  3. MUST NOT añadir el Fragment al DAG.
  4. MUST NOT afectar al estado de los Fragments existentes.

9.6.4 Agreement Desconocido (3001)

Cuando un Fragment referencia un Agreement_ID desconocido:

  1. El receptor MUST descartar el Fragment.
  2. Devolver el error AGREEMENT_NOT_FOUND.
  3. MAY disparar la re-negociación (definido por la implementación).

9.6.5 Clave No Lista (2002)

Cuando se intenta la transmisión de datos antes de que se complete el intercambio de claves de CAP:

  1. El DTP_Engine MUST rechazar el envío.
  2. MUST devolver el error KEY_NOT_READY al llamador de capa superior.
  3. MUST NOT responder en texto plano sobre el canal de comunicación.

9.6.6 Caché Llena (6001)

Cuando la caché de Fragments no acusados alcanza su límite superior:

  1. El emisor MUST pausar el envío de nuevos Fragments.
  2. Enviar una notificación BUFFER_FULL a la aplicación de capa superior.
  3. Reanudar el envío después de que el espacio de caché se libere mediante acuses de recibo.
  4. MUST NOT descartar Fragments ya en caché.

9.6.7 Timeout de Retransmisión (6002)

Cuando el contador de retransmisión del Fragment se agota:

  1. El emisor MUST notificar a la aplicación de capa superior el error RETRANSMISSION_TIMEOUT.
  2. SHOULD disparar la suspensión o terminación de la Session.
  3. MUST NOT retransmitir indefinidamente.

9.6.8 Incompatibilidad de Versión (7001)

Cuando se recibe un marco con una versión de protocolo incompatible (véase el Capítulo 10 para más detalles):

  1. El receptor MUST no procesar el marco.
  2. MUST devolver el error VERSION_INCOMPATIBLE.
  3. MUST incluir la versión más alta que soporta en el campo details del error.

9.6.9 Permiso Denegado (8001, 8002)

Para operaciones de rol ilegales:

  1. El DTP_Engine MUST rechazar la operación.
  2. Las operaciones de escritura del Observer MUST devolver OBSERVER_WRITE_DENIED (8002).
  3. Otros rechazos de permiso MUST devolver PERMISSION_DENIED (8001).

9.7 Estrategia de Recuperación de Errores

Una implementación MUST adoptar la estrategia de recuperación correspondiente por tipo de error:

Categoría de ErrorEstrategia de Recuperación
1xxx Procesamiento de marcosDescartar marco, registrarlo, continuar recibiendo marcos subsiguientes
2xxx CifradoFallo único: descartar marco; fallos consecutivos: disparar re-negociación de claves
3xxx AgreementDescartar Fragment; puede disparar re-negociación
4xxx DAGCiclo: rechazar; no resuelto: almacenar en caché y esperar
5xxx SessionIntentar la recuperación de la Session; cerrar en caso de fallo
6xxx ReanudaciónPausar el envío, esperar la respuesta del peer o la intervención de la capa superior
7xxx VersiónEnviar notificación de versión; intentar la degradación
8xxx PermisoRechazar la operación; MUST NOT reintentar automáticamente

Una implementación MUST NOT reintentar automáticamente la misma operación cuando ocurre un error de permiso (8xxx).