Saltar al contenido
Lección 4 de 12

Prompting para Depuración

9 min read

Por Qué los Prompts de Depuración Son Diferentes

La depuración es la tarea donde la calidad del prompt importa más. Cuando generas código, un prompt mediocre aún te da algo con lo que trabajar. Cuando depuras, un prompt vago te da el diagnóstico equivocado -- y la corrección equivocada puede introducir nuevos bugs mientras enmascara el original.

El desafío fundamental con los prompts de depuración es que estás describiendo una brecha entre el comportamiento esperado y el actual. La IA necesita entender ambos lados de esa brecha, más el código que los conecta, para identificar la causa raíz. Omite cualquier pieza y la IA adivinará -- y adivinar la causa de un bug es cómo pasas horas persiguiendo el problema equivocado.

La Plantilla de Prompt para Depuración

Cada prompt efectivo de depuración incluye cinco piezas de información:

1. COMPORTAMIENTO ACTUAL: Que pasa ahora mismo (el bug)
2. COMPORTAMIENTO ESPERADO: Que deberia pasar en su lugar
3. PASOS PARA REPRODUCIR: Como disparar el bug
4. MENSAJE DE ERROR: El texto exacto del error, stack trace o log
5. CONTEXTO DE CODIGO RELEVANTE: El codigo involucrado en el bug

Veamos cada componente en acción.

Comportamiento Actual

Malo:

La app esta rota

Bueno:

Cuando un usuario envia el formulario de registro con un email y password
validos, la API devuelve un codigo de estado 500 en lugar de crear la cuenta
de usuario.

Sé específico sobre lo que pasa: ¿la página se rompe? ¿Muestra un error? ¿Se cuelga? ¿Devuelve datos incorrectos? ¿Falla silenciosamente?

Comportamiento Esperado

Malo:

Deberia funcionar

Bueno:

La API deberia crear un nuevo registro de usuario en la base de datos, hashear
el password con bcrypt, y devolver un codigo de estado 201 con el objeto de
usuario (sin el campo de password).

Definir el comportamiento esperado ayuda a la IA a entender tu intención. A veces el "bug" es en realidad el código funcionando como fue diseñado pero no coincidiendo con tus expectativas -- la IA necesita conocer tus expectativas para distinguir entre ambas situaciones.

Pasos para Reproducir

Pasos para reproducir:
1. Navegar a /register
2. Ingresar email: test@example.com, password: "ValidPass123!"
3. Hacer clic en "Crear Cuenta"
4. Observar la pestana de red: POST /api/auth/register devuelve 500

Esto sucede con cada email nuevo. Los emails existentes correctamente
devuelven 409.

Los pasos de reproducción ayudan a la IA a rastrear la ruta de ejecución exacta. Incluir lo que funciona (emails existentes devuelven 409) es tan importante como lo que no funciona porque reduce dónde vive el bug.

Mensaje de Error

Siempre incluye el texto exacto del error. Copia y pega -- no parafrasees.

Malo:

Muestra algun tipo de error de base de datos

Bueno:

Error de los logs del servidor:

PrismaClientKnownRequestError:
Invalid `prisma.user.create()` invocation:
The required column `user.email_verified` has no default value, and no value
was provided in the create data.

at src/routes/auth.ts:47:28
at processTicksAndRejections (node:internal/process/task_queues:95:5)

El mensaje de error exacto le dice a la IA precisamente qué salió mal. En este caso, la IA puede identificar inmediatamente que la columna email_verified es requerida pero no se está estableciendo en la llamada create -- una corrección de una línea.

Contexto de Código Relevante

Proporciona el código involucrado en el bug. No copies el archivo completo -- enfócate en la función relevante y sus dependencias inmediatas.

Aqui esta el handler de registro (src/routes/auth.ts, lineas 35-55):

async function register(req: Request, res: Response) {
  const { email, password } = req.body;
  const hashedPassword = await bcrypt.hash(password, 10);
  const user = await prisma.user.create({
    data: {
      email,
      passwordHash: hashedPassword,
    },
  });
  res.status(201).json({ id: user.id, email: user.email });
}

Y aqui esta el esquema Prisma para User:

model User {
  id             String   @id @default(uuid())
  email          String   @unique
  passwordHash   String
  emailVerified  Boolean
  createdAt      DateTime @default(now())
}

Con los cinco componentes, la IA puede ver inmediatamente que emailVerified es un Boolean requerido sin valor por defecto, y la llamada create no lo incluye. Solución: agregar emailVerified: false a los datos de creación o agregar @default(false) al esquema.

Poniéndolo Todo Junto

Aquí hay un prompt de depuración completo que combina los cinco componentes:

Bug: El endpoint de registro devuelve 500 para nuevos usuarios.

Comportamiento actual: POST /api/auth/register devuelve 500 con un error de
Prisma al crear un nuevo usuario con email y password validos.

Comportamiento esperado: Deberia crear el usuario y devolver 201 con el
objeto de usuario.

Pasos para reproducir: POST a /api/auth/register con body
{ "email": "new@test.com", "password": "ValidPass123!" }. Sucede para cada
email nuevo. Email existente correctamente devuelve 409 Conflict.

Mensaje de error:
PrismaClientKnownRequestError: Invalid `prisma.user.create()` invocation:
The required column `user.email_verified` has no default value.
at src/routes/auth.ts:47:28

Codigo relevante: El handler register en src/routes/auth.ts crea un usuario
con solo los campos email y passwordHash, pero el esquema Prisma requiere
emailVerified (Boolean sin valor por defecto).

Por favor corrige este bug y explica la causa raiz.

La Técnica de Alcance Estrecho

Una de las técnicas de depuración más valiosas es estrechar el alcance de tu descripción. Cuanto más amplio el alcance, más tiene que buscar la IA. Cuanto más estrecho el alcance, más enfocada la corrección.

Alcance amplio (lento, frecuentemente incorrecto):

El sistema de autenticacion no esta funcionando correctamente. Los usuarios
tienen problemas para iniciar sesion.

Alcance estrecho (rápido, preciso):

El formulario de login en src/pages/Login.tsx se envia exitosamente
(POST /api/auth/login devuelve 200 con un JWT valido), pero el hook useAuth()
en AuthContext no actualiza isAuthenticated a true. El router.push('/dashboard')
en la linea 42 de Login.tsx se dispara antes de que la actualizacion de estado
se complete, asi que el guard de autenticacion de la ruta del dashboard
redirige de vuelta a login. Esto crea un bucle de redireccion infinito entre
/login y /dashboard.

El prompt de alcance estrecho le da a la IA una imagen completa de la cadena del bug. Sabrá inmediatamente que debe mirar el timing de la actualización de estado asíncrono, no la validación de JWT, la respuesta de la API, ni el envío del formulario.

Patrones Comunes de Prompts de Depuración

Patrón 1: Explica Este Error

Explica este error en el contexto de mi proyecto Express + Prisma + TypeScript:

TypeError: Cannot read properties of undefined (reading 'id')
    at getUserOrders (src/routes/orders.ts:23:35)
    at Layer.handle (node_modules/express/lib/router/layer.js:95:5)

La funcion getUserOrders intenta acceder a req.user.id, pero req.user es
undefined. El authMiddleware deberia adjuntar el objeto usuario a req. Aqui
esta el codigo del middleware: [pegar middleware]. Aqui esta el registro de
la ruta: [pegar configuracion de ruta].

Patrón 2: Por Qué X Devuelve Y en Lugar de Z

En src/utils/dateFormatter.ts, la funcion formatRelativeDate('2026-03-25')
devuelve "en 0 dias" en lugar de "ayer" cuando se llama el 26 de marzo de 2026.

Aqui esta la funcion:
[pegar codigo de la funcion]

Espero que devuelva "ayer" para fechas exactamente un dia en el pasado.
Parece que el calculo de diferencia de dias esta redondeando hacia abajo en
lugar de usar el limite del dia calendario.

Patrón 3: Rastrear el Flujo de Datos

Rastrear el flujo de datos de la orden de un usuario desde la creacion hasta
la visualizacion:

1. Usuario hace clic en "Realizar Pedido" en src/components/Checkout.tsx
2. Esto llama a createOrder() en src/services/orderService.ts
3. Que hace POST a /api/orders
4. El handler en src/routes/orders.ts crea la orden con Prisma
5. La respuesta regresa al frontend
6. La orden deberia aparecer en src/pages/OrderHistory.tsx

La orden se crea en la base de datos (puedo verla en psql), pero no aparece
en la pagina OrderHistory. En que punto de esta cadena se estan perdiendo
los datos?

[pegar codigo relevante de la consulta de lista de ordenes y el componente]

Incluyendo Contexto de Entorno

A veces los bugs son específicos del entorno. Cuando sospechas esto, incluye los detalles del entorno:

Este bug solo sucede en produccion, no en desarrollo local.

Entorno:
- Node.js 20.11.0 (produccion), 20.10.0 (local)
- PostgreSQL 15 en AWS RDS (produccion), PostgreSQL 15 Docker local
- Detras de AWS ALB con terminacion SSL
- Variables de entorno configuradas via AWS Secrets Manager

La API devuelve datos correctos localmente pero devuelve arrays vacios en
produccion para la misma consulta de base de datos. La base de datos tiene
datos (verificado con conexion directa psql).

Sospecho que el string de conexion a la base de datos o la configuracion
SSL podrian diferir. Aqui esta nuestra configuracion de conexion a la base
de datos: [pegar codigo]

Anti-Patrón: El Volcado de Logs

No pegues 200 líneas de logs y digas "encuentra el bug." La IA se perderá en información irrelevante y podría enfocarse en advertencias o ruido en lugar del error real.

Malo:

Aqui estan los logs, encuentra que esta mal:
[200 lineas de logs mezclados de info, warning y error]

Bueno:

Aqui esta el error relevante de los logs (filtrado de la salida completa):

[ERROR] 2026-03-26T10:15:32Z OrderService.createOrder: Foreign key constraint
failed on field `customerId`. Customer ID "cust_abc123" does not exist in the
customers table.

Este error ocurre al procesar ordenes desde nuestro webhook handler. El
webhook recibe eventos de Stripe, y el customerId viene del metadata del
cliente en Stripe. Creo que el problema es que no estamos creando el registro
del cliente antes de procesar la primera orden.

Filtra tus logs. Resalta el error relevante. Proporciona tu hipótesis. Esto convierte una investigación de 10 minutos en una corrección de 30 segundos.

La Técnica de la Hipótesis

Cuando tienes una teoría sobre lo que está mal, inclúyela. Incluso si tu hipótesis es incorrecta, le da a la IA un punto de partida y le muestra dónde ya has investigado.

Bug: La conexion WebSocket se cae cada 60 segundos.

Mi hipotesis: Nuestro proxy inverso Nginx tiene un proxy_read_timeout por
defecto de 60 segundos, y los frames WebSocket no se estan enviando con
suficiente frecuencia para mantener la conexion viva. Creo que necesitamos
ya sea un heartbeat ping/pong o un timeout aumentado.

Configuracion relevante: [pegar config de Nginx]
Configuracion de WebSocket: [pegar codigo WS del servidor]

Es correcta mi hipotesis? Si no, que mas podria causar desconexiones
exactamente cada 60 segundos?

Esto evita que la IA explore caminos sin salida y enfoca el análisis en las causas más probables. Y si tu hipótesis es incorrecta, la IA explicará por qué y sugerirá alternativas.