StackPractices
beginner Por Mathias Paulenko

Plantilla de Reporte de Bug (Markdown + Ejemplos)

Plantilla estructurada de reporte de bugs para que los equipos reproduzcan, clasifiquen y resuelvan defectos más rápido, con ejemplo completo.

Usa esta plantilla cuando un bug tiene que pasar de “alguien vio algo raro” a un ticket que un ingeniero pueda resolver sin otra reunión.

Resumen

Un reporte de bug tiene un solo trabajo: darle a quien lo corrige todo lo necesario para reproducir el problema en una sola lectura. Los reportes que omiten pasos o datos del entorno vuelven como “falta información” y quedan semanas sin tocar. La estructura de abajo existe para eliminar ese ida y vuelta.

La plantilla reúne ocho piezas de información:

  1. Resumen — una oración: qué falla, dónde y bajo qué condición
  2. Pasos de reproducción — numerados, aislados, desde un estado conocido
  3. Comportamiento esperado vs actual — define qué significa “corregido”
  4. Entorno — SO, navegador, versión de la app, ambiente de despliegue
  5. Introducido en — la primera versión donde aparece el bug, si se conoce
  6. Severidad — una evaluación de impacto estandarizada para el triaje
  7. Evidencia — capturas de pantalla, logs e IDs de request
  8. Contexto — frecuencia, trabajo relacionado y cambios recientes

Cuándo Usarla

  • Trackers internos — cualquier bug que caiga en GitHub Issues, Jira, Linear o GitLab se beneficia del mismo conjunto de campos.
  • Traspaso de QA a ingeniería — los testers ya recopilan pasos y datos del entorno; la plantilla evita que algo se pierda de camino al backlog.
  • Proyectos open source — quienes reportan desde fuera no conocen tus convenciones; la plantilla es la forma de pedir datos de reproducción sin un hilo de comentarios.
  • Escalaciones de soporte — el equipo de soporte traduce “la exportación está rota” en algo accionable; la plantilla es su checklist.

Cuándo no usarla:

  • Vulnerabilidades de seguridad — nunca pongas pasos de reproducción de un exploit en un tracker público; usa el canal privado de divulgación descrito en Variantes.
  • Incidentes activos — si producción está caída, ejecuta primero el proceso de incidentes. El reporte de bug viene después, normalmente como salida del postmortem del incidente.
  • Solicitudes de feature — un comportamiento nuevo que nunca se diseñó no es un bug. Usa la plantilla de solicitud de feature.

Plantilla

# Reporte de Bug

## Resumen
Descripción de una oración: qué falla, dónde y bajo qué condición.

## Pasos para Reproducir
1. Ir a '...'
2. Hacer clic en '...'
3. Observar el error

## Comportamiento Esperado
Lo que debería haber pasado.

## Comportamiento Actual
Lo que pasó en su lugar. Cita el texto exacto del error.

## Entorno
- **SO:** [ej. macOS 14, Windows 11]
- **Navegador:** [ej. Chrome 126, Safari 17]
- **Versión de la app:** [ej. v2.4.1]
- **Ambiente:** [staging / producción / local]

## Introducido En
Primera versión o commit donde aparece el bug, si se conoce. "Funcionaba en v2.3.x, roto en v2.4.0" es suficiente — le dice al ingeniero dónde mirar.

## Severidad
- [ ] Crítica — pérdida de datos, brecha de seguridad, caída total
- [ ] Alta — feature principal roto, solución alternativa difícil
- [ ] Media — feature degradado, existe solución alternativa
- [ ] Baja — problema cosmético, inconveniente menor

## Evidencia
- Captura o grabación de pantalla:
- Error de consola, stack trace o llamada de red fallida (ID de request):
- Logs relevantes:

## Contexto Adicional
- Frecuencia (siempre / intermitente / una vez)
- Enlaces a issues, PRs o [solicitudes de feature](/docs/feature-request-template/) relacionadas
- Cambios recientes que puedan estar relacionados

Escribir un Buen Título

El título es la única línea que sobrevive en resultados de búsqueda, colas de triaje e hilos de Slack. La fórmula: qué falla + dónde + bajo qué condición.

Mal:   "La exportación no funciona"
Bien:  "Exportar CSV devuelve un archivo vacío cuando el rango cruza un mes"

Mal:   "Login roto"
Bien:  "Login con SSO redirige a /error tras autenticar correctamente (solo Okta)"

Las versiones buenas además son buscables — la siguiente persona con el mismo bug las encuentra por el texto del error en lugar de abrir un duplicado.

Ejemplo Completo

# Reporte de Bug: Exportar CSV descarga un archivo vacío cuando el rango de fechas cruza un mes

## Resumen
Exportar datos de analytics como CSV produce un archivo vacío cuando el rango
seleccionado cruza un límite de mes (ej. 28 de marzo a 3 de abril).

## Pasos para Reproducir
1. Navegar a /analytics/dashboard
2. Seleccionar el rango de fechas 2026-03-28 a 2026-04-03
3. Hacer clic en "Export CSV" en el gráfico "Revenue by Day"
4. Abrir el archivo descargado

## Comportamiento Esperado
El CSV contiene 7 filas de datos (una por día) con las columnas date, revenue, orders.

## Comportamiento Actual
El CSV se descarga solo con encabezados y cero filas de datos. No aparece ningún
error en la UI ni en la consola del navegador.

## Entorno
- **SO:** macOS 14.4
- **Navegador:** Chrome 126.0
- **Versión de la app:** v2.4.1
- **Ambiente:** producción

## Introducido En
Funcionaba en v2.3.9, roto desde el despliegue de v2.4.0. La refactorización del
rango de fechas en el PR #412 es la sospechosa.

## Severidad
- [x] Alta — exportación rota para un caso de uso común, sin solución alternativa

## Evidencia
- Log del servidor: la query devuelve 0 filas para `WHERE date >= '2026-03-28' AND date <= '2026-04-03'` — apunta a un bug de parsing de fechas
- ID de request: req-9f2a-81c3 (buscable en Kibana)

## Contexto Adicional
- Se reproduce siempre que el rango cruza un límite de mes; rangos de un solo mes funcionan
- Candidato a regresión — el selector de rango se lanzó en v2.4.0
- Escribir un test de regresión encaja con el flujo de [Test-Driven Development](/guides/test-driven-development-guide/)

Por Qué Funciona Esta Estructura

SecciónPropósito
ResumenEl lector decide la prioridad en cinco segundos
Pasos de reproducciónEl ingeniero puede confirmar el bug en local
Esperado vs actualDefine qué significa “corregido”
EntornoLos bugs suelen ser específicos de plataforma o datos
Introducido enApunta al cambio que probablemente lo causó
SeveridadOrdena la cola de triaje
EvidenciaAhorra el ida y vuelta de “¿puedes adjuntar los logs?”
Contexto adicionalEnlaza trabajo relacionado y pistas de causa raíz

Severidad vs Prioridad

La severidad mide el impacto; la prioridad decide el orden de trabajo. A menudo divergen, y confundirlas es la forma más rápida de atascar una reunión de triaje:

  • Un typo en la página de login es severidad baja pero prioridad alta — lo ve todo el mundo.
  • Un crash que solo afecta a un SO fuera de soporte es severidad alta, pero puede esperar un sprint.

Quien reporta propone la severidad porque conoce el impacto. Quien hace triaje asigna la prioridad porque ve toda la cola. Si tu tracker tiene un campo de prioridad, ocúltalo a quienes reportan — la gente siempre elige la más alta.

Una regla práctica que se sostiene: la severidad es una propiedad del bug, la prioridad es una propiedad del roadmap. Reclasifica cuando cambie cualquiera de las dos.

Definiciones de Severidad

SeveridadCriteriosTiempo de respuestaEjemplo
CríticaPérdida de datos, brecha de seguridad, caída totalInmediato (< 1 hora)Todas las requests de la API devuelven 500
AltaFeature principal roto, sin solución alternativa tolerableMismo día (< 8 horas)La exportación produce un archivo vacío
MediaFeature degradado, existe solución alternativaEste sprint (< 1 semana)Dirección de ordenación invertida en una columna
BajaProblema cosmético, inconveniente menorPróximo sprintEl color del botón no coincide con el diseño

Ciclo de Vida del Bug

La mayoría de los trackers usan las mismas transiciones con nombres distintos — Jira tiene “To Do / In Progress / Done”, GitHub lo hace con etiquetas. El flujo es el mismo:

flowchart diagram: subgraph Entrada
  1. Reportado — quien reporta completa la plantilla y crea un ticket
  2. Clasificado — un revisor lo etiqueta dentro de 24 horas (bug, frontend, needs-repro, wont-fix)
  3. Reproducido — un ingeniero confirma que el bug existe en local o en staging
  4. Asignado — un ingeniero toma ownership y empieza la investigación
  5. En progreso — causa raíz identificada, corrección en marcha
  6. PR abierto — corrección enviada con un test de regresión; la plantilla de PR debería referenciar el ID del bug
  7. Verificado — quien reporta o QA confirma que el fix resuelve el problema
  8. Cerrado — ticket cerrado con la versión del fix y anotado en las release notes

Consejos para Quienes Reportan

  • Reprodúcelo dos veces antes de reportar — los problemas transitorios necesitan otro manejo
  • Aísla los pasos — quita las acciones ajenas del camino de reproducción
  • Prueba en modo incógnito — descarta extensiones del navegador
  • Revisa los issues existentes primero — los duplicados desperdician tiempo de triaje; busca por el texto del error, no por el título
  • Incluye capturas o grabaciones de pantalla — los bugs visuales son difíciles de describir
  • Adjunta logs relevantes — consola del navegador, logs del servidor, pestaña de red
  • Anota la frecuencia — “siempre pasa” vs “1 de cada 10 veces” cambia la prioridad
  • Menciona cambios recientes — “empezó después del despliegue de v2.4.0” acota la búsqueda

Consejos para Equipos de Triaje

  • Etiqueta de inmediato — bug, frontend, backend, needs-reproduction
  • Asigna en 24 horas — los bugs sin asignar se pudren
  • Pide la información faltante rápido — usa la plantilla como checklist
  • Cierra reportes estancados — sin actividad en 90 días significa cerrarlo con una nota
  • Enlaza duplicados — fusiona los reportes del mismo problema en lugar de dejar hilos paralelos
  • Verifica la severidad — quienes reportan tienden a inflarla; ajústala durante el triaje y explica por qué

Ejemplo de Reporte de Bug (Formato Ticket)

Los mismos campos, aplanados en un ticket de texto plano — el formato en el que terminan Jira o los hilos de email:

=== Reporte de Bug: error 500 al exportar pedidos ===

Título: Error 500 al exportar más de 1000 pedidos a CSV
ID: BUG-1234
Reportado por: bob@company.com
Fecha: 2026-07-12
Severidad: Alta
Ambiente: Producción
Introducido en: v2.4.0

Comportamiento Esperado:
  Al hacer clic en "Exportar CSV" en la página de pedidos con un
  filtro de fecha que devuelve más de 1000 pedidos se descarga un
  CSV con todas las filas.

Comportamiento Actual:
  El sistema devuelve un error 500 después de ~30 segundos.
  El log muestra "Database timeout."

Pasos para Reproducir:
  1. Iniciar sesión como administrador
  2. Ir a /admin/pedidos
  3. Seleccionar el rango de fechas 2026-06-01 a 2026-07-01
  4. Hacer clic en "Exportar CSV"
  5. Esperar ~30 segundos
  6. Observar el error 500 en el navegador

Evidencia:
  - Captura del error (adjunta)
  - Stack trace: https://pastebin.company.com/abc123
  - ID de request: req-abc-456 (buscable en Kibana)

Frecuencia:
  - Siempre reproducible con > 1000 pedidos
  - Funciona correctamente con < 500 pedidos
  - Intermitente entre 500 y 1000 pedidos

Impacto:
  - El equipo de ventas no puede exportar los pedidos mensuales
  - Solución temporal: exportar por semana (4 exportaciones)
  - 15 usuarios afectados

Entorno:
  - Navegador: Chrome 126.0
  - SO: macOS 14.5
  - Versión de la app: v2.4.3
  - Región: us-east-1

Notas Adicionales:
  - El endpoint es GET /api/orders/export
  - El timeout de la BD es 30s; la query tarda ~45s con más de 1000 pedidos

Variantes

Una sola plantilla no le sirve a todo el mundo. Las cuatro variantes de abajo cubren los ajustes habituales: estructura forzada en GitHub, formulario reducido para clientes, reportes de crash generados por máquina y un canal privado para seguridad.

Formulario de Issue de GitHub (YAML)

GitHub puede imponer esta plantilla de forma nativa. Coloca el archivo de abajo en .github/ISSUE_TEMPLATE/bug-report.yml y quienes reportan verán un formulario estructurado en lugar de un cuadro de texto vacío:

name: Bug Report
description: File a bug report.
title: "[Bug]: "
labels: ["bug", "triage"]
body:
  - type: textarea
    id: summary
    attributes:
      label: What happened?
      description: One or two sentences. What did you expect instead?
    validations:
      required: true
  - type: textarea
    id: repro
    attributes:
      label: Steps to reproduce
      description: Numbered steps from a known starting state.
      placeholder: |
        1. Go to '...'
        2. Click on '...'
        3. Observe the error
    validations:
      required: true
  - type: dropdown
    id: version
    attributes:
      label: Version
      description: First version where you saw the bug.
      options:
        - v2.4.x
        - v2.3.x
        - older
    validations:
      required: true
  - type: dropdown
    id: severity
    attributes:
      label: Severity
      options:
        - Critical
        - High
        - Medium
        - Low
    validations:
      required: true
  - type: textarea
    id: logs
    attributes:
      label: Logs and evidence
      description: Console errors, stack traces, request IDs. Remove credentials and personal data first.
      render: shell

validations.required es la parte que rinde frutos — el reporte no puede enviarse sin pasos de reproducción. Referencia completa de campos en la documentación de issue forms de GitHub.

Orientada al cliente (portal de soporte)

Los clientes no deberían ver etiquetas de severidad ni campos internos. Usa un formulario simplificado — Resumen, ¿Qué intentabas hacer?, ¿Qué pasó en su lugar?, subida de captura — y luego convierte los envíos en reportes internos durante el triaje.

Reporte de crash (automatizado)

Los reportes automáticos de crash del error tracking (Sentry, Bugsnag, Crashlytics) rellenan la plantilla solos: stack trace, datos del dispositivo, versión de la app, acciones del usuario antes del crash y frecuencia. Consulta la receta de manejo de errores para el reporte estructurado de errores.

Reporte de vulnerabilidad de seguridad

Los reportes de seguridad necesitan una plantilla diferente: los pasos de reproducción no van en un ticket público. Usa un canal privado de divulgación e incluye el componente afectado, el vector de ataque, el impacto potencial y la mitigación sugerida. La checklist de auditoría de seguridad cubre el proceso alrededor.

Adaptar la Plantilla a Tu Tracker

TrackerMecanismoDónde vive la plantillaCampos obligatorios
GitHub IssuesFormularios de issue (YAML).github/ISSUE_TEMPLATE/validations.required por campo
GitLab IssuesPlantillas de descripción.gitlab/issue_templates/Bug.mdPor convención — sin enforcement de schema
JiraTipo de issue Bug + screen schemeConfiguración del proyectoCampos requeridos en la config de campos
LinearPlantillas de issueConfiguración del equipoParcial — título y cuerpo prellenados

Sea cual sea el tracker, conserva los cinco campos centrales — resumen, pasos, esperado, actual, entorno. Si la herramienta no puede imponerlos, pon el checklist dentro del cuerpo de la plantilla para que quien reporta lo vea mientras escribe.

Cuando el proceso cambia — un nivel de severidad nuevo, un estado renombrado — actualiza todas las plantillas en el mismo pull request. Los trackers divergen rápido: el formulario de GitHub pide un campo que la pantalla de Jira no tiene, y seis meses después la mitad de los reportes llegan sin entorno. Trata la plantilla como un artefacto vivo, versionado junto al código que describe.

Medir la Calidad de los Reportes

Si eres responsable del proceso de triaje, unos pocos números dicen si la plantilla está funcionando:

  • Tiempo hasta reproducción — días entre “reportado” y “reproducido”. Si se alarga, a los reportes les faltan pasos o datos del entorno.
  • Tasa de rebote — la proporción de reportes devueltos como needs-info. Por encima del ~20 %, la plantilla pide cosas equivocadas u oculta campos obligatorios.
  • Tasa de duplicados — mucha duplicación significa que el bug es muy visible (sube su prioridad) o que la búsqueda del tracker falla.
  • Tasa de verificación — correcciones confirmadas por quien reporta. Los fixes que nadie verifica suelen volver como tickets reabiertos.

Errores Comunes

  • Título vago — “exportación rota” obliga a una pregunta de seguimiento; “exportar CSV vacío cuando el rango cruza un mes” no.
  • Varios bugs en un solo reporte — cada bug necesita su propio responsable, severidad y corrección. Si los juntas, se corrige el fácil y el ticket se cierra con el difícil aún abierto.
  • Inflación de severidad — cuando todo es Crítico, el triaje deja de creer en la etiqueta.
  • Pasos sin estado inicial — “haz clic en Exportar” asume que el lector sabe que estabas en /admin/orders con un filtro de junio. Empieza desde un estado cerrado de sesión o limpio.
  • Sin datos del entorno — casi todos los hilos de “en mi máquina funciona” son un campo de entorno que falta. SO, navegador y versión toman 30 segundos.
  • Capturas con secretos — tokens de auth en headers, emails de clientes, hostnames internos. Recorta o censura antes de subir.
  • Duplicados buscados por título — quienes reportan buscan con sus propias palabras, no con el texto del error. Busca por el mensaje de error o el endpoint.
  • Corregir sin test de regresión — el fix debería reproducir el bug primero, o vuelve en otra forma. Integration testing cubre cómo verificar entre entornos.

Preguntas frecuentes

¿Qué pasa si no puedo reproducir el bug de forma consistente?

Reporta igualmente. Marca la frecuencia como "intermitente" e incluye marcas de tiempo, logs y cualquier patrón que hayas notado — "solo después de 10 minutos de inactividad" es una pista real.

¿Los clientes deberían usar esta plantilla también?

Sí, pero simplificada. Los clientes reciben un formulario solo con Resumen, Pasos y Entorno; los equipos internos reciben la plantilla completa con campos de severidad y contexto.

¿Cómo manejo los bugs de "en mi máquina funciona"?

Añade verificaciones de paridad de entorno: Docker, versiones exactas de dependencias, datos de prueba sembrados. Si solo ocurre en producción, el bug está en los datos o la configuración, no en el código.

¿Cuál es la diferencia entre un bug y una solicitud de feature?

Un bug es un comportamiento que no coincide con el comportamiento documentado o intencionado. Una solicitud de feature pide un comportamiento que nunca se diseñó. Si es ambiguo, revisa la especificación o pregunta al product owner, y luego usa la plantilla de solicitud de feature para capacidades nuevas.

¿Qué información es obligatoria en un reporte de bug?

Obligatorio: título descriptivo, pasos para reproducir, comportamiento esperado vs actual, entorno y frecuencia. Recomendado: capturas, stack traces, IDs de request, impacto en usuarios y cualquier solución temporal. Un reporte sin pasos de reproducción no se puede confirmar — si no puedes reproducirlo, dilo y da el contexto.

¿Cómo determinamos la severidad de un bug?

La severidad mide el impacto en el negocio, no la complejidad técnica. Crítica significa servicio caído o pérdida de datos (resolver en 24 h); Alta significa una feature principal rota para muchos usuarios (48 h); Media significa que existe una solución alternativa (este sprint); Baja significa impacto menor (30 días). Pregúntate: ¿cuántos usuarios, con qué frecuencia, hay solución alternativa, afecta a los ingresos? La severidad puede bajar tras el triaje — documenta el motivo cuando cambie.

¿Cómo manejamos los reportes de bug duplicados?

Busca en el tracker por las palabras del error antes de crear un reporte — no por el título, porque cada quien lo formula distinto. Si ya existe, añade tus hallazgos como comentario en lugar de abrir un duplicado. Si no estás seguro, créalo marcado como "posible duplicado de #XXX". Cinco duplicados del mismo bug son una señal para subirle la prioridad.

¿Qué pasa si el bug está en una dependencia de terceros?

Regístralo en tu tracker interno para visibilidad, y también en el issue tracker de la dependencia con un enlace entre ambos tickets. Anota la versión de la dependencia y si existe una solución temporal — y si la dependencia está abandonada, dilo y empieza a planear la migración.