Seguridad Guía

Códigos de diagnóstico de errores: cómo funcionan y cómo se investigan

Guía funcional y técnica del sistema de diagnóstico de errores de Neges: qué es el código de 8 caracteres, cómo viaja la información desde el navegador hasta los logs, dónde vive cada pieza del código, un caso real resuelto de punta a punta, y un análisis honesto de las brechas que quedan abiertas.

32 min de lectura

Cuando algo falla en el backoffice, Neges muestra un código corto como ABGNWS7T. Este documento explica qué hay detrás de ese código: qué información se recoge, qué se descarta deliberadamente, cómo se correlaciona con los logs del servidor y cómo se usa para encontrar la causa de un fallo. Sirve a tres lectores: quien reporta un problema, quien lo investiga y quien mantiene el sistema. Describe el comportamiento implementado al 3 de agosto de 2026; el código y las pruebas siguen siendo la fuente de verdad.

Qué resuelve, en una página

Un reporte de error útil necesita dos cosas que casi nunca vienen juntas: contexto suficiente para explicar el fallo, y una forma de comunicarlo que no dependa de que el usuario sepa describir lo que pasó. Pedirle a alguien que copie un volcado técnico funciona mal —se pierde, se trunca, se pega incompleto—, y pedirle que cuente qué hizo produce relatos que rara vez coinciden con lo que registró el servidor.

Neges resuelve esto separando ambas cosas. El contexto completo viaja al backend por su propio canal, cifrado en tránsito y sin pasar por el portapapeles del usuario. Lo que el usuario recibe es una referencia de ocho caracteres, legible en voz alta, que apunta a ese contexto. El usuario dicta un código; quien investiga recupera un expediente.

Las tres preguntas que el sistema responde y dónde se responde cada una.
PreguntaQuién la respondeDato clave
¿Qué pidió el usuario?Línea de acceso del servidormétodo, ruta, estado, duración, bytes
¿Por qué se rechazó?Controller de dominiorazón concreta y forma de lo recibido
¿Qué creía el navegador que enviaba?Reporte del clientectx.*, versión de app, navegador

Cómo funciona para quien reporta el problema

Cuando una acción falla, aparece un aviso con el mensaje del error y un botón para copiar el diagnóstico. Ese botón es el que activa todo el mecanismo.

  1. Ocurre el error

    El aviso muestra un título y un mensaje en lenguaje llano. Hasta aquí no se envió nada: el diagnóstico está armado en memoria, esperando.

    Tip: Si el aviso desaparece antes de que alcances a tocarlo, la acción se puede repetir para reproducirlo.
  2. Tocas «Copiar diagnóstico»

    En ese momento el navegador envía el expediente al backend. El botón pasa por «Enviando…» y termina en «Código copiado».

  3. Recibes un código de ocho caracteres

    Queda copiado en el portapapeles con el formato «Neges — código de diagnóstico: ABGNWS7T». Ese texto es lo único que hace falta enviar a soporte.

  4. Soporte recupera el expediente

    Con ese código se localizan las líneas de log correspondientes, que incluyen qué se pidió, por qué falló, con qué dispositivo y qué había hecho la sesión justo antes.

Hay un modo degradado. Si el envío falla —sin conexión, o el backend caído, que es justo cuando los errores se acumulan— el botón copia en su lugar el texto completo del diagnóstico, legible y pegable tal cual. El usuario nunca se queda sin algo que enviar.

  • El código es de ocho caracteres, sin las letras I, L, O ni U.
  • No distingue mayúsculas de minúsculas al dictarlo, pero se copia en mayúsculas.
  • No caduca: la fila queda guardada en la base de datos.
  • No contiene datos: no sirve de nada intentar «leerlo» sin acceso a los logs.

Arquitectura del sistema

El sistema atraviesa dos aplicaciones y tres destinos de escritura. Ninguna pieza conoce a todas las demás: el interceptor no sabe qué es una subida de imagen, el controller de dominio no sabe qué es un toast, y el servicio de reportes no sabe qué claves trae el contexto.

arquitectura.mmdmermaid
El diagrama se renderiza al cargar la pagina.
Responsabilidad de cada componente.
ComponenteResponsabilidadQué NO hace
Call siteDeclara contexto y origen en el HttpContext del requestNo conoce el formato del reporte ni del log
httpErrorToastInterceptorIntercepta toda respuesta, registra migajas y captura metadataNo decide si se envía un reporte
HttpRequestBreadcrumbsServiceMantiene una ventana rodante de 20 eventos de sesiónNo persiste nada ni sale del navegador por su cuenta
HttpErrorDiagnosticsServiceArma el payload y el texto legible a partir del errorNo transporta: no hace peticiones
ToastComponentMuestra el aviso y, si el usuario lo pide, envía el reporteNo arma el diagnóstico
http-access-logGenera el requestId, lo expone como cabecera y loguea el accesoNo conoce el dominio de la petición
api/client-error-reportNormaliza, asigna referencia, persiste y logueaNo confía en el tenant ni el usuario que declare el cliente

El flujo completo, paso a paso

La secuencia tiene una particularidad que conviene entender antes de leer el código: la captura y el armado del diagnóstico ocurren en momentos distintos y en lugares distintos. El interceptor tiene el request en la mano pero no sabe si habrá toast; el toast sabe que hay error pero ya perdió el request.

flujo-captura.mmdmermaid
El diagrama se renderiza al cargar la pagina.

El puente entre ambos momentos es un WeakMap indexado por la instancia del error. El interceptor deposita ahí la metadata; el servicio de diagnóstico la recupera cuando el toast se lo pide. Como la clave es el objeto de error, la entrada se libera sola cuando ese error deja de estar referenciado: no hay fuga de memoria ni limpieza manual.

http-error-diagnostics.service.tstypescript
// neges-backoffice/src/app/core/http/http-error-diagnostics.service.ts
//
// La metadata se indexa por la INSTANCIA del error en un WeakMap. Eso permite
// separar el momento de la captura (el interceptor, que tiene el request en
// mano) del momento del armado (el toast, que solo tiene el error).

private readonly metadataByError = new WeakMap<HttpErrorResponse, HttpErrorRequestMetadata>();

capture(error: unknown, request: HttpRequest<unknown>): void {
  if (!(error instanceof HttpErrorResponse)) {
    return;
  }

  this.metadataByError.set(error, {
    // Se lee aquí y no en buildDiagnostic: el request solo está en alcance
    // mientras el interceptor maneja la falla.
    context: normalizeDiagnosticContext(request.context.get(HTTP_ERROR_CONTEXT)),
    method: request.method.toUpperCase(),
    occurredAt: new Date().toISOString(),
    source: normalizeDiagnosticValue(request.context.get(HTTP_ERROR_SOURCE)),
    url: request.urlWithParams,
  });
}
estados-toast.mmdmermaid
El diagrama se renderiza al cargar la pagina.

Correlación: el requestId y la referencia

El sistema usa dos identificadores con propósitos distintos, y confundirlos es la fuente más común de tiempo perdido en una investigación.

Dos identificadores, dos audiencias.
IdentificadorFormatoLo generaSirve para
requestIdUUID v4El middleware, en cada peticiónUnir las líneas de log entre sí
reference8 caracteresEl servicio de reportes, al enviarQue una persona lo dicte

El middleware genera el requestId al comienzo de cada petición, lo guarda en el estado del contexto para que cualquier capa posterior pueda loguearlo, y lo devuelve al navegador en la cabecera X-Request-Id. El backoffice la lee de la respuesta de error y la incluye en el reporte. Ese ida y vuelta es lo que permite que una referencia dictada por teléfono termine señalando la línea exacta del servidor.

correlacion.mmdmermaid
El diagrama se renderiza al cargar la pagina.

Contrato de datos y límites de confianza

Todo lo que envía el navegador es entrada no confiable, incluso viniendo de una sesión autenticada. El sistema aplica normalización en dos capas independientes: una en el cliente, para no recoger de más, y otra en el servidor, que no asume nada sobre la primera.

capas-de-confianza.mmdmermaid
El diagrama se renderiza al cargar la pagina.

El normalizador del servidor es una lista blanca: cualquier campo que no lea explícitamente se descarta antes de guardar. Para el contexto, que es abierto por diseño, el filtro es por forma del valor en lugar de por nombre de clave.

client-error-report.tstypescript
// neges-strapi/src/api/client-error-report/services/client-error-report.ts
//
// El cliente declara las claves de context, así que el filtro es por FORMA del
// valor y no por nombre: las claves útiles cambian según el call site, pero un
// contexto de diagnóstico siempre es primitivos planos.

const normalizeContext = (value: unknown) => {
  if (!isRecord(value)) {
    return {};
  }

  const normalized: Record<string, ClientErrorReportContextValue> = {};

  for (const [key, entry] of Object.entries(value)) {
    const safeKey = key.replace(/[^\w.-]/g, '').slice(0, MAX_CONTEXT_KEY_LENGTH);

    if (!safeKey || Object.keys(normalized).length >= MAX_CONTEXT_ENTRIES) {
      continue;
    }

    if (entry === null) { normalized[safeKey] = null; continue; }
    if (typeof entry === 'boolean') { normalized[safeKey] = entry; continue; }
    if (typeof entry === 'number' && Number.isFinite(entry)) { normalized[safeKey] = entry; continue; }
    if (typeof entry === 'string') { normalized[safeKey] = readText(entry, MAX_CONTEXT_VALUE_LENGTH); }
  }

  return normalized;
};
Límites aplicados al guardar. Existen para acotar el tamaño y para impedir que un payload malicioso falsifique líneas de log.
CampoLímiteRazón
message1000 caracteresMensajes de API pueden ser largos
userAgent400 caracteresSuficiente para identificar navegador y sistema
breadcrumbs20 eventosVentana rodante; se filtra antes de recortar
context12 clavesEvita que un cliente use el reporte como almacenamiento
clave de context40 caracteresSe limpian los caracteres fuera de [\w.-]
valor de context120 caracteresDebe caber en una línea de log
Todo textoSin saltos de líneaImpide inyectar líneas de log falsas

Las rutas se guardan con la query redactada: se conserva el nombre de cada parámetro, porque la forma de la consulta suele explicar el fallo, pero el valor se reemplaza salvo para una lista corta de parámetros que describen configuración de pantalla y no contenido escrito por el usuario.

Anatomía de la referencia

client-error-report.tstypescript
// Alfabeto estilo Crockford: sin I, L, O ni U, para que una referencia
// sobreviva a ser leída en voz alta por teléfono o transcrita a mano.
const REFERENCE_ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
const REFERENCE_LENGTH = 8;
const REFERENCE_MAX_ATTEMPTS = 5;

export const generateClientErrorReportReference = (): string =>
  Array.from(
    { length: REFERENCE_LENGTH },
    () => REFERENCE_ALPHABET[randomInt(REFERENCE_ALPHABET.length)]
  ).join('');

// 32^8 = 1,1 billones de combinaciones. La columna es única y una colisión
// se reintenta hasta 5 veces antes de fallar.

La elección del alfabeto no es estética. Una referencia se dicta por teléfono, se escribe en un ticket y se transcribe a mano; quitar los caracteres que se confunden entre sí —I con 1, O con 0, L con 1, U con V— elimina la clase de error más frecuente en ese recorrido. La longitud de ocho da un espacio de unos 1,1 billones de combinaciones, más que suficiente para que las colisiones sean anecdóticas, y aun así la columna es única y el servicio reintenta hasta cinco veces con una referencia nueva antes de rendirse.

Las tres líneas de log

Un fallo instrumentado produce tres líneas, escritas por tres componentes que no se conocen entre sí, unidas por el requestId. Este es el formato canónico.

ejemplo-de-logs.txtbash
# 1. Línea de dominio — la escribe el controller al rechazar
warn: image-asset-upload: rejected reason="An image file is required."
      contentType=multipart/form-data boundary=true contentLength=0
      bodyKeys=none fileKeys=none file:absent requestId=3f8c36f1-...

# 2. Línea de acceso — la escribe el middleware para toda petición
warn: http: POST /api/image-assets/idxf6.../media 400 35ms
      requestId=3f8c36f1-... bytes=0 tenant=z3kd2zhb... user=1 code=ValidationError

# 3. Línea de reporte — la escribe el servicio cuando el usuario envía el diagnóstico
warn: client-error-report: reference=ABGNWS7T status=400 path=/api/image-assets/idxf6.../media
      source=assets:image-asset-media-upload requestId=3f8c36f1-...
      tenant=z3kd2zhb... user=1 app=v0.0.0 (fa9c355)
      ctx.appendedIsBlob=true ctx.appendedSize=2742487 ctx.appendedType=image/png
      ctx.hasFileInfoEntry=true ctx.hasFilesEntry=true ctx.sourceExtension=png
      ctx.sourceNameLength=40 ctx.sourceSize=2742487 ctx.sourceType=image/png
      ua="Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) ... Safari/604.1"

La línea de reporte se construye con una función pura y probada, no armada al vuelo dentro del servicio. Esa decisión es deliberada: si una referencia solo sirve cuando alguien puede consultar la base de datos, entonces el formato de la línea deja de ser un detalle de implementación y pasa a ser el contrato de soporte. Como tal, tiene pruebas que verifican que cada campo esperado aparece y que los ausentes se omiten en lugar de imprimir marcadores vacíos.

Caso real: el diagnóstico ABGNWS7T

La instrumentación descrita aquí se construyó a raíz de un fallo que resistió varias rondas de análisis. Subir una foto a un producto fallaba de forma intermitente en producción con un error genérico —«An image file is required»— y con el asset ya creado, que el propio flujo revertía. Vale la pena seguirlo completo porque muestra qué tipo de pregunta responde cada línea.

  1. Lo que se sabía sin instrumentación

    Solo que el servidor no encontraba el archivo en el cuerpo multipart. Con eso, las hipótesis plausibles eran al menos cuatro, todas en componentes distintos, y ninguna se podía descartar.

  2. Lo que dijo la línea de dominio

    contentType=multipart/form-data con boundary presente, pero contentLength=0, bodyKeys=none y fileKeys=none. La petición llegó bien formada y completamente vacía.

  3. Lo que dijo el reporte del cliente

    ctx.appendedIsBlob=true, ctx.appendedSize=2742487, ctx.appendedType=image/png. El navegador tenía un blob de 2,74 MB con su tipo correcto, correctamente agregado al FormData.

  4. La conclusión

    El cuerpo se perdió entre el navegador y el cable. WebKit no pudo leer el contenido del blob al serializar la petición y envió un cuerpo vacío en lugar de fallar.

La corrección fue forzar una lectura real de los bytes antes de entregar el archivo al transporte. Si la lectura falla o devuelve cero, el usuario recibe un mensaje claro y accionable en lugar de una petición vacía; si funciona, el transporte recibe un buffer en memoria que siempre puede leer. La instrumentación también dejó una lección sobre sí misma: la primera versión comparaba el archivo consigo mismo, así que no habría detectado un encogimiento entre el procesamiento y el envío.

arbol-de-decision.mmdmermaid
El diagrama se renderiza al cargar la pagina.

Dónde vive cada cosa

Mapa de archivos para quien tenga que modificar el sistema, humano o agente de código.

mapa-de-repositorios.txtbash
neges-backoffice/
  src/app/core/http/
    http-error-toast.context.ts          # 3 tokens de HttpContext
    http-error-toast.interceptor.ts      # punto de captura
    http-error-diagnostics.models.ts     # contrato del payload
    http-error-diagnostics.service.ts    # arma el diagnóstico
    http-error-diagnostics.utils.ts      # normalización y texto legible
    http-request-breadcrumbs.service.ts  # ventana de 20 eventos
    http-error-toast.service.ts          # decide y arma el toast
    client-error-report.service.ts       # transporte del reporte
    http-error.utils.ts                  # lectura de código y mensaje
  src/app/core/toast/toast.model.ts      # ToastPayload con diagnóstico
  src/app/shared/ui/toast/               # UI, envío y portapapeles
  src/app/features/assets/data-access/
    asset-upload.service.ts              # único call site con contexto

neges-strapi/
  config/cors.ts                         # expone X-Request-Id
  src/middlewares/http-access-log.ts     # requestId, línea de acceso, bytes
  src/utils/request-context.ts           # contexto asíncrono del requestId
  src/api/client-error-report/
    routes/                              # POST, solo require-auth
    controllers/                         # deriva tenant y usuario
    services/                            # allowlist, referencia y log
    content-types/                       # esquema y unicidad
  src/api/image-asset/controllers/       # sobre multipart al rechazar
Los tres tokens de HttpContext que gobiernan el comportamiento del sistema.
TokenTipoPor defectoEfecto
HTTP_ERROR_PRESENTATION'auto' | 'inline' | 'silent' | 'toast''auto'Decide si el error muestra aviso. En «silent» no se muestra nada
HTTP_ERROR_SOURCEstring''Identifica pantalla y control; aparece como source= en el log
HTTP_ERROR_CONTEXTRecord<string, primitivo>{}Hechos del request; aparecen como ctx.* en el log

Buenas prácticas aplicadas

El diseño coincide con varias prácticas establecidas de la industria. Vale la pena nombrarlas explícitamente, tanto para justificar las decisiones como para saber contra qué medir las que faltan.

Prácticas reconocidas y cómo se materializan en Neges.
PrácticaRecomendación generalImplementación en Neges
Identificador de correlaciónGenerar el identificador lo antes posible en el flujo, propagarlo y devolverlo al clienteUUID por petición en el primer middleware, expuesto como X-Request-Id
Referencia para soporte separada del traceUn identificador técnico para observabilidad y otro legible para el usuariorequestId para los logs, referencia de 8 caracteres para la persona
Migajas de sesiónRegistrar la actividad previa al fallo, evitando datos personalesVentana de 20 eventos con solo método, ruta redactada, estado y código
Minimización de datosFiltrar en el cliente antes de enviar y volver a filtrar en el servidorDos normalizadores independientes, ninguno confía en el otro
Lista blanca sobre lista negraDescartar por defecto lo que no se reconoce explícitamenteEl normalizador del servidor ignora todo campo que no lee
Prevención de inyección en logsNeutralizar saltos de línea en cualquier valor que llegue a un logSe eliminan en toda normalización de texto, con prueba dedicada
Envío explícitoNo exfiltrar contexto sin intervención del usuarioEl reporte solo se envía al tocar el botón

La decisión de enviar el expediente por un canal propio en lugar de ponerlo en el portapapeles merece mención aparte. Es lo que hace seguro recoger contexto extra: el payload nunca atraviesa el canal donde el usuario acabe pegándolo, que puede ser un chat de grupo, un correo reenviado o un ticket público.

Análisis de brechas

Lo siguiente son limitaciones verificadas del sistema al 3 de agosto de 2026, no hipótesis. Están ordenadas por impacto.

Brechas abiertas, con su consecuencia concreta.
#BrechaConsecuenciaSeveridad
1No existe ruta de lectura de reportesLa tabla solo acepta POST. Para resolver un código hay que entrar a los logs de la plataforma o a la base de datos: nadie fuera del equipo técnico puede hacerloAlta
2Sin política de retención ni purgaLa tabla crece sin límite. La minimización de datos exige que la información personal no se conserve más de lo necesario, y aquí no hay borrado programadoAlta
3Sin límite de tasa en el endpointEl repositorio ya tiene una utilidad de rate limiting en uso en otros endpoints, pero no está aplicada aquí. Una sesión autenticada puede inundar la tablaMedia
4errorCode no cae a error.nameEl lector de códigos del backoffice consulta details.code y error.code, pero Strapi envía el tipo en error.name. La línea de reporte sale sin code= aunque la de acceso sí lo tengaMedia
5Sesgo de muestreoSolo se reportan los errores cuyo aviso el usuario decide enviar. Los errores que se ignoran o cuyo aviso se cierra no producen ningún reporteMedia
6Sin agrupación ni huella de errorCada reporte es una fila aislada. No hay forma de responder «esto ocurrió 47 veces esta semana» sin consultar la base a manoMedia
7Logs en texto plano, no estructuradosLas líneas son key=value dentro de un mensaje de texto. La búsqueda es por subcadena y no se pueden hacer consultas por campo ni agregacionesMedia
8Sin propagación de contexto entre serviciosEl requestId es propio y muere en Strapi. No viaja a los servicios satélite, así que un fallo que los cruce no se puede seguir de punta a puntaBaja
9Sin alertasEl descubrimiento es reactivo: alguien avisa. Un pico de reportes no dispara nadaBaja
10Adopción del contexto: un solo call siteEl mecanismo es genérico, pero solo la subida de imágenes lo usa. El resto de los errores llegan sin ctx.*Baja

Mejoras propuestas

Propuestas concretas, ordenadas por relación entre valor y esfuerzo. Cada una es independiente de las demás.

  1. Fallback de errorCode en la ruta de diagnóstico

    Cierra la brecha 4 con un cambio mínimo. Conviene aplicarlo solo en el camino del diagnóstico y no en el lector compartido de códigos: ese lector alimenta las comprobaciones de sesión del interceptor de autenticación, y ampliar lo que devuelve tiene un alcance mayor que el que justifica el arreglo.

    Tip: El middleware del servidor ya hace este fallback, y su comentario dice replicar el comportamiento del backoffice. Los dos lados se desincronizaron.
  2. Purga programada de reportes

    Cierra la brecha 2. Una tarea periódica que borre reportes con más de noventa días, alineada con las retenciones habituales para registros operativos. Como el sistema ya tiene infraestructura de tareas programadas, el trabajo es acotado.

  3. Límite de tasa por usuario

    Cierra la brecha 3 reutilizando la utilidad que ya existe en el repositorio. Un tope por sesión y ventana es suficiente: el envío es una acción manual y un volumen alto ya es señal de anomalía.

  4. Ruta de lectura y pantalla mínima

    Cierra la brecha 1. Un endpoint de lectura por referencia, restringido a operadores, más una vista simple. Convierte el código en algo autoservicio y elimina la dependencia del acceso a la plataforma de despliegue.

  5. Huella de agrupación

    Cierra la brecha 6. Un hash estable derivado de ruta, código de error y origen, guardado junto al reporte, permite contar ocurrencias y detectar regresiones sin agregar infraestructura.

  6. Emisión estructurada en JSON

    Cierra la brecha 7. Emitir el mismo contenido como objeto en lugar de texto permite consultas por campo y agregaciones. El formato de texto puede convivir como salida legible en desarrollo.

  7. Adoptar el contexto en más call sites

    Cierra la brecha 10 y es la de mejor retorno a largo plazo. Cada formulario o importador que declare cuatro o cinco hechos sobre lo que envía convierte su próximo fallo en algo que se lee en vez de investigarse.

  8. Propagación estándar de contexto de trazas

    Cierra la brecha 8. Adoptar la cabecera estándar de contexto de trazas junto al identificador propio permite seguir una operación a través de los servicios satélite, manteniendo la referencia legible para soporte.

Cómo extender el sistema

Instrumentar un call site nuevo no requiere tocar el interceptor, el normalizador ni el formato del log. Todos son genéricos.

ejemplo-de-instrumentacion.tstypescript
// Receta: instrumentar un call site nuevo.
//
// 1. Importar los tokens.
import { HTTP_ERROR_CONTEXT, HTTP_ERROR_SOURCE } from '@core/http/http-error-toast.context';
import { HttpErrorContext } from '@core/http/http-error-diagnostics.models';

// 2. Describir lo que la URL no dice. Solo primitivos planos, sin datos personales.
function buildContext(input: ImportInput): HttpErrorContext {
  return {
    rowCount: input.rows.length,
    hasHeaderRow: input.hasHeaderRow,
    delimiter: input.delimiter,
    encoding: input.encoding,
  };
}

// 3. Adjuntarlo al request.
return this.http.post(url, body, {
  context: new HttpContext()
    .set(HTTP_ERROR_CONTEXT, buildContext(input))
    .set(HTTP_ERROR_SOURCE, 'stock:inventory-count-import'),
});

// No hace falta tocar nada más: el interceptor, el normalizador del servidor y
// la línea de log ya son genéricos. Las claves nuevas aparecen como ctx.rowCount,
// ctx.delimiter, etcétera.
  • Usar solo primitivos planos: cadena, número, booleano o nulo.
  • No incluir datos personales ni contenido escrito por el usuario.
  • Preferir hechos verificables sobre interpretaciones: tamaños, banderas y conteos.
  • Cuando haya dos valores que puedan discrepar, enviar ambos: la discrepancia es el diagnóstico.
  • Nombrar el origen con el formato pantalla:control, para distinguir call sites que comparten endpoint.
  • Mantener el total por debajo de doce claves: el servidor descarta las que sobren.

Para instrumentar un rechazo del lado del servidor, el patrón es capturar el error, escribir una línea que describa la forma de lo recibido —no solo el motivo— y volver a lanzarlo sin alterarlo. Describir la forma es lo que separa «faltaba el archivo» de «el archivo llegó pero el parser lo clasificó como campo», que son bugs distintos en componentes distintos.

Referencias

¿Te fue útil este contenido?

Tu feedback nos ayuda a mejorar la documentación de Neges.

Soporte humano

¿No encuentras lo que buscas?

Conversa con nuestro equipo de soporte en español. Respondemos por WhatsApp, correo o ticket en menos de 24 horas hábiles.

contacto@neges.clLun a Vie · 9 a 18 hrs
+56 9 5379 1163WhatsApp Business