Errores de la API de multas que conviene reintentar y cuáles no

Repetir una solicitud sólo ayuda cuando la causa del error puede desaparecer sola. Clasificar por causa, y no por código de estado, define qué se reintenta, qué espera una acción y qué se cierra.

Foto de Marco FerreiroMarco FerreiroAutor en multas.ar
4 min de lectura
Mesa de oficina con sobres de papel madera separados en tres pilas frente a un mueble de casilleros de madera, con luz natural lateral.
Mesa de oficina con sobres de papel madera separados en tres pilas frente a un mueble de casilleros de madera, con luz natural lateral.

Un cliente HTTP puede reintentar cualquier cosa. La pregunta operativa es cuáles vale la pena: un reintento que no puede cambiar el resultado consume cupo, alarga la espera de quien consultó una patente y esconde el problema real detrás de un error genérico.

La respuesta pocas veces está en el código de estado. Un error es reintentable cuando su causa puede dejar de existir con el paso del tiempo, sin que nadie intervenga. Esa propiedad pertenece a la causa, no al número que la transporta. Esta nota ordena la tabla que traduce causas en destinos; cómo repetir sin duplicar el efecto lo trata la nota sobre reintento seguro.

El código de estado es una primera aproximación

RFC 9110 separa los errores atribuidos al cliente de los atribuidos al servidor y describe el 503 como una sobrecarga temporal o un mantenimiento programado, que puede acompañarse de una espera sugerida. Es un buen punto de partida y un mal punto final.

La propia especificación lo admite: para las dos familias de error pide que el servidor mande una representación que explique la situación y si la condición es temporal o permanente. Ese dato no viaja en el número sino en el cuerpo, y sólo si el proveedor lo puso. Bajo un mismo error del servidor conviven el portal de una jurisdicción saturado, que vuelve solo, y un defecto del pedido, que fallará igual la semana que viene.

Tres destinos, no dos

La tabla de clasificación gana cuando deja de ser binaria:

  • reintento automático, para causas que se resuelven solas: cortes de conexión, saturación declarada como temporal y rechazos por ritmo, con la espera que indique el servidor;
  • reintento diferido, para causas que persisten hasta que alguien actúa: credencial vencida, cupo del período agotado, un campo obligatorio ausente o los casos de RFC 6585 en que hay que agregar una precondición o autenticarse ante la red antes de volver a pedir;
  • cierre con motivo, para causas que no van a cambiar: un pedido malformado, un trámite que la jurisdicción dio de baja, un identificador que la fuente no reconoce.

El segundo grupo es el que más se maltrata. Colapsarlo con el tercero convierte un problema accionable —renovar una clave, ampliar un cupo, corregir una patente mal cargada— en un descarte que nadie mira: necesita una cola con la causa visible, no un contador de fallas.

El timeout no entra derecho en la primera fila: su causa suele ser transitoria, pero deja sin saber si la consulta de la patente llegó a ejecutarse. RFC 9110 admite el reintento automático cuando el cliente puede detectar que el pedido original nunca se aplicó, y ése es el trabajo de esa fila: primero verificar, después repetir.

La tabla también cubre las fallas que llegan dentro de una respuesta exitosa. Cuando una consulta agrega varias fuentes, el transporte funciona y un organismo se cae igual: esa causa necesita su fila y apunta el reintento a la parte pendiente, no a la consulta entera, según la nota sobre timeouts y resultados parciales.

Una sola tabla, y un default honesto

La clasificación debería vivir en un único lugar y tener una llave estable. RFC 9457 pide que el consumidor use el tipo del problema —una URI— como identificador primario, y desaconseja sacar información del texto escrito para personas, que puede cambiar de redacción o de idioma sin aviso.

Para lo que no encaja en ninguna fila hace falta un default explícito. Ni transitorio —multiplica llamadas inútiles— ni definitivo, que puede transformar una caída general en una respuesta sin infracciones. Una clase “sin clasificar”, con uno o dos intentos espaciados y revisión, deja la evidencia para agregar la fila que falta.

Presupuesto por operación y evidencia para corregir

El presupuesto se fija por operación de negocio, no por llamada. Si el cliente HTTP, la cola y la aplicación reintentan por su cuenta, los intentos se multiplican y una jurisdicción lenta recibe una avalancha. Conviene un tope de intentos y de tiempo total para la operación, con el ritmo espaciado que describe la nota sobre rate limits interpretables.

Revisar la tabla exige ver los intentos juntos. W3C Trace Context define un identificador que distingue una traza completa a través de varios servicios; no habla de reintentos, así que propagarlo en cada intento es una decisión del cliente. Tomada esa decisión, se puede medir por causa qué proporción de reintentos termina en éxito.

Ese número corrige la tabla. Una causa cuyos reintentos casi nunca cambian el resultado está mal ubicada en la primera fila; una que recién se resuelve al tercer intento indica un presupuesto corto, no un error definitivo.

Qué revisar antes de automatizar

La revisión que rinde es sobre la tabla, no sobre la biblioteca: dónde vive, quién la edita, con qué llave se busca cada fila, qué destino recibe lo que no encaja y si el presupuesto es por operación.

La prueba es simple: mirá los errores de la última semana y preguntá, causa por causa, qué habría cambiado esperando un minuto. Las filas donde la respuesta es “nada” no merecen un reintento; merecen que alguien se entere.

Metodología

Alcance
Cómo clasificar las fallas de una integración de consultas vehiculares para decidir cuáles se reintentan automáticamente. No cubre el mecanismo para repetir sin duplicar el efecto ni la política de espera entre intentos, tratados en otras notas.
Unidad de análisis
Una causa de falla declarada por el proveedor u observada por el cliente, con el destino que se le asigna en la tabla de clasificación.
Cobertura
Semántica de errores y condiciones temporales según RFC 9110, códigos adicionales según RFC 6585, errores tipados según RFC 9457 y propagación de contexto de traza según W3C Trace Context. El criterio es independiente del proveedor.

Limitaciones

  • Sin tipos de error estables publicados por el proveedor, el cliente clasifica por heurística y esa heurística envejece con cada cambio de la API.
  • La tabla de clasificación describe el comportamiento observado de un servicio, no una garantía contractual de que una causa volverá a comportarse igual.
  • Las mismas reglas aplicadas a operaciones con costo por consulta y a lecturas gratuitas producen presupuestos distintos, que cada organización define.

Fuentes

Preguntas frecuentes

¿Todos los errores del servidor se pueden reintentar?

No por defecto. RFC 9110 describe el 503 como una sobrecarga temporal o un mantenimiento programado, y pide que el servidor explique en la respuesta si la condición es temporal o permanente, justamente porque el código no lo dice. Si los reintentos de una causa nunca cambian el resultado, esa causa está mal clasificada.

¿Qué hago con un error que no sé clasificar?

Tratarlo como una clase propia: uno o dos intentos espaciados, registro de la respuesta completa y revisión posterior. Asumir que es transitorio multiplica llamadas inútiles; asumir que es definitivo puede convertir una caída real en un resultado vacío.

¿Sirve clasificar leyendo el mensaje de error?

Es frágil. RFC 9457 pide que el consumidor use el tipo del problema como identificador primario y desaconseja sacar información del texto pensado para personas, que puede cambiar de redacción o de idioma sin previo aviso.

¿Una respuesta exitosa puede contener un error que hay que reintentar?

Sí, cuando el cuerpo describe el estado de varias fuentes. El transporte funcionó y una fuente falló igual. Esa falla necesita la misma clasificación que un error HTTP, y el reintento debería apuntar a la parte pendiente y no a la consulta completa.

Notas relacionadas