ConstructiCat Logo
CodeBust.
Browse section ▾

API alucinada.

Código generado por IA que llama a funciones, métodos, parámetros, claves de configuración o paquetes que parecen plausibles pero que no existen en la versión real de la biblioteca de la que dependes.

##Signs and Symptoms

Un revisor detecta una API alucinada cuando el código se lee con fluidez y "parece" un uso idiomático de una biblioteca, pero la llamada, opción o importación concreta no aparece en la superficie real de esa biblioteca. Señales reveladoras:

  • Un método u opción cuyo nombre es demasiado conveniente: hace exactamente lo que pedía el prompt, con un nombre que mezcla dos APIs reales (p. ej. findLastWhere, includesAll, parseDateSafe).
  • Parámetros inventados sobre una función real (la variante peligrosa: a menudo compila y solo falla en tiempo de ejecución, o ignora la opción en silencio).
  • Una import de un paquete que no está en package.json / requirements.txt, o una importación con nombre que el módulo nunca exporta.
  • Formas de API que mezclan versiones: una firma de la v2 invocada sobre un cliente de la v5, o un método eliminado/renombrado hace varias versiones.
  • Comentarios en línea confiados que afirman que la llamada es correcta ("// devuelve el cargo reembolsado").
// Generado por IA — fluido, plausible y erróneo
import { formatRelative } from 'date-fns';

// `roundingMethod` está inventado — date-fns no expone tal opción, se ignora en silencio
const label = formatRelative(date, new Date(), { roundingMethod: 'floor' });

// `findLastWhere` no existe en Array — TypeError en tiempo de ejecución
const lastActive = items.findLastWhere(i => i.active);

// Llamada de SDK mezclada: la forma real de Stripe es stripe.refunds.create({ charge })
await stripe.charges.refund(chargeId, { amount: 500 });

Una heurística rápida: si no puedes señalar la entrada de documentación o la definición de tipo de una llamada de terceros en menos de un minuto, trátala como alucinada hasta que se demuestre lo contrario.

##Reasons for the Problem

Por qué los modelos lo producen

  • Plausibilidad del siguiente token, no búsqueda. Un LLM predice la continuación estadísticamente más probable, que es en la práctica el promedio de todas las APIs similares que ha visto. Ese promedio a menudo es un método que debería existir: el modelo emite "el nombre conveniente" en lugar del real. Los estudios sobre recomendación de APIs encuentran que el 58,1 %–84,1 % de las APIs recomendadas no existen en el paquete nombrado, y el error dominante son nombres de métodos inexistentes (arXiv 2404.00971, ACM TOSEM 2025).
  • Mezcla de versiones. Los corpus de entrenamiento mezclan muchas versiones de una biblioteca, así que el modelo fusiona las firmas de la v2 y la v5 en una que no coincide con ninguna. Estas "alucinaciones por conflicto de conocimiento" (p. ej. parámetros inexistentes) son precisamente del tipo que se cuela ante los linters y falla en tiempo de ejecución.
  • Desactualización por la fecha de corte del entrenamiento. El modelo usa con total seguridad APIs renombradas, obsoletas o eliminadas desde su fecha de corte, y recurre a lo que más aparecía en el corpus, lo que según OX Security implica que se recomiendan versiones de paquetes más antiguas, a veces vulnerables (informe de OX, oct. 2025).
  • Sin contexto de repositorio/dependencias. Sin tu package.json ni el código fuente real del módulo, el modelo inventa ayudantes que "parecen" pertenecer a tu stack.
  • Adulación / afán de responder. El asistente casi nunca dice "no estoy seguro de que ese método exista": produce código confiado y de aspecto ejecutable, lo que rebaja la sospecha del revisor.
  • El determinismo lo hace explotable. La alucinación de paquetes no es ruido aleatorio: en 16 modelos y 2,23 millones de generaciones, el 19,7 % de los paquetes recomendados eran ficticios (205 474 nombres únicos), y el 58 % de las alucinaciones se repetía en 10 reintentos de prompt (USENIX Security 2025; resumen de SecurityWeek).

Por qué resulta perjudicial

  • Corrección. Los parámetros inventados y las opciones silenciosamente ignoradas producen comportamientos incorrectos en rutas de código que las pruebas rara vez cubren; el fallo aflora en producción, no en tiempo de compilación.
  • Seguridad / cadena de suministro. Un nombre de paquete alucinado es un objetivo de registro: los atacantes publican malware con el nombre predicho, así que el siguiente desarrollador que acepta la sugerencia lo instala: el ataque de slopsquatting (término acuñado por Seth Larson, de la PSF). La variante de desactualización reintroduce en silencio APIs obsoletas o con CVE.
  • Carga de revisión. El código plausible traslada a los revisores la carga de verificar cada llamada desconocida contra la documentación; la prosa fluida hace que esa verificación sea menos probable.
  • Acumulación de deuda técnica. Los desarrolladores suelen pegar el stub alucinado "casi funcional" y parchear a su alrededor en lugar de corregir la llamada raíz, alimentando la tendencia general de la era de la IA de aumento del copiar/pegar y caída de la refactorización (GitClear 2025: clones multiplicados ~8×, líneas movidas por refactorización caídas del 25 % a <10 %). Este patrón ya está catalogado entre los olores de código específicos de la IA (arXiv 2509.20491).

##Treatment

Tácticas de proceso y de prompting

  • Ancla el modelo en superficies reales. Pega en el contexto los stubs de tipos reales, la página de documentación pertinente o el código fuente de la versión instalada, o usa una herramienta de recuperación de documentación (estilo Context7 / RAG). Indícale las versiones exactas de las dependencias de tu lockfile.
  • Exige citas. Pide al modelo que nombre la entrada oficial de documentación o la firma de tipo de cada llamada de terceros que use. Regla práctica: toda llamada a un método de una biblioteca de terceros debe poder rastrearse hasta su entrada de documentación antes de aprobar el PR.
  • Hazlo ejecutar, en el bucle. Exige que pasen tsc / mypy / pylint / la compilación y la batería de pruebas, y haz que el agente realmente ejecute npm install / pip install para que un paquete alucinado falle rápido en lugar de llegar a la revisión.
  • Pídele que reutilice, no que invente. Aliméntalo con un grep del módulo existente e indícale que llame a los ayudantes existentes (reutiliza los ayudantes de utils/http.ts) en lugar de conjurar nuevos: esto también contrarresta el olor de duplicación de ayudante reinventado.
  • Controla las dependencias. Usa un lockfile + una lista de permitidos de instalación y un escáner de cadena de suministro (Socket/Snyk) antes de añadir cualquier paquete nuevo, para que no se cuelen nombres con slopsquatting.

La refactorización del código

Reemplaza la llamada inventada por la real verificada. Si de verdad quieres la comodidad que imaginó el modelo, impleméntala una sola vez contra la API real detrás de un envoltorio de Extraer función en lugar de esparcir la llamada falsa.

// Antes — parámetro alucinado + forma de SDK mezclada
async function refundLast(chargeId: string) {
  // `stripe.charges.refund` y esta forma de opciones no existen
  return stripe.charges.refund(chargeId, { amount: 500, reason: 'requested' });
}

// Después — verificado contra los tipos/documentación del SDK de Stripe instalado,
// y la "comodidad" envuelta una sola vez para no repetir la API real
async function refundCharge(chargeId: string, amountCents: number) {
  return stripe.refunds.create({
    charge: chargeId,
    amount: amountCents,
    reason: 'requested_by_customer',
  });
}

Para la variante de desactualización, trata una llamada obsoleta señalada como una tarea real de actualización: pásate a la API actual y fija la versión, en lugar de silenciar la advertencia.

Límites. Los verificadores de tipos y los resolvedores detectan el subconjunto resoluble (objetos tipados, importaciones no resueltas). El resto dinámico/sin tipos —opciones inventadas sobre any, claves de configuración en cadenas, campos de payload REST— no tiene un detector automatizado fiable y debe verificarlo una persona contra la documentación real.

##Detected by