ConstructiCat Logo
CodeBust.
Browse section ▾

API hallucinée.

Code généré par IA qui appelle des fonctions, méthodes, paramètres, clés de configuration ou paquets qui semblent plausibles mais n'existent pas dans la version réelle de la bibliothèque dont vous dépendez.

##Signs and Symptoms

Un relecteur repère une API hallucinée quand le code se lit avec fluidité et « ressemble » à un usage idiomatique d'une bibliothèque, alors que l'appel, l'option ou l'import précis est introuvable dans la surface réelle de cette bibliothèque. Signes révélateurs :

  • Une méthode ou une option dont le nom est trop pratique — elle fait exactement ce que le prompt demandait, avec un nom qui mélange deux API réelles (par ex. findLastWhere, includesAll, parseDateSafe).
  • Des paramètres inventés sur une fonction réelle (la variante dangereuse — elle compile souvent et n'échoue qu'à l'exécution, ou ignore silencieusement l'option).
  • Un import d'un paquet qui n'est pas dans package.json / requirements.txt, ou un import nommé que le module n'exporte jamais.
  • Des formes d'API qui mélangent les versions : une signature v2 appelée sur un client v5, ou une méthode supprimée/renommée plusieurs versions auparavant.
  • Des commentaires inline confiants affirmant que l'appel est correct (« // renvoie la charge remboursée »).
// Généré par IA — fluide, plausible, et faux
import { formatRelative } from 'date-fns';

// `roundingMethod` est inventé — date-fns n'expose aucune option de ce nom, elle est silencieusement ignorée
const label = formatRelative(date, new Date(), { roundingMethod: 'floor' });

// `findLastWhere` n'existe pas sur Array — TypeError à l'exécution
const lastActive = items.findLastWhere(i => i.active);

// Appel SDK mélangé : la vraie forme Stripe est stripe.refunds.create({ charge })
await stripe.charges.refund(chargeId, { amount: 500 });

Une heuristique rapide : si vous ne pouvez pas pointer vers l'entrée de documentation ou la définition de type d'un appel tiers en moins d'une minute, traitez-le comme halluciné jusqu'à preuve du contraire.

##Reasons for the Problem

Pourquoi les modèles le produisent

  • Plausibilité du token suivant, pas une recherche. Un LLM prédit la continuation statistiquement la plus probable, ce qui revient à la moyenne de chaque API similaire qu'il a vue. Cette moyenne est souvent une méthode qui devrait exister — le modèle émet « le nom pratique » plutôt que le vrai. Les études sur la recommandation d'API constatent que 58,1 % à 84,1 % des API recommandées n'existent pas dans le paquet nommé, et l'erreur dominante est le nom de méthode inexistant (arXiv 2404.00971, ACM TOSEM 2025).
  • Mélange de versions. Les corpus d'entraînement mêlent de nombreuses versions d'une bibliothèque, donc le modèle fusionne les signatures v2 et v5 en une seule qui ne correspond à aucune. Ces « hallucinations en conflit avec la connaissance » (par ex. des paramètres inexistants) sont précisément le genre qui passe à travers les linters et échoue à l'exécution.
  • Obsolescence liée à la date limite d'entraînement. Le modèle utilise avec assurance des API renommées, dépréciées ou supprimées depuis sa date limite, et se rabat sur ce qui apparaissait le plus dans le corpus — ce qui, selon OX Security, signifie que des versions de paquets plus anciennes, parfois vulnérables, sont recommandées (rapport OX, oct. 2025).
  • Aucun contexte de dépôt/dépendances. Sans votre package.json ni la source réelle du module, le modèle invente des helpers qui « semblent » appartenir à votre stack.
  • Complaisance / empressement à répondre. L'assistant ne dit presque jamais « je ne suis pas sûr que cette méthode existe » — il produit un code confiant et d'apparence exécutable, ce qui abaisse la méfiance du relecteur.
  • Le déterminisme le rend exploitable. L'hallucination de paquet n'est pas un bruit aléatoire : sur 16 modèles et 2,23 M de générations, 19,7 % des paquets recommandés étaient fictifs (205 474 noms uniques), et 58 % des hallucinations se reproduisaient en l'espace de 10 relances (USENIX Security 2025 ; synthèse SecurityWeek).

Pourquoi c'est nuisible

  • Exactitude. Des paramètres inventés et des options silencieusement ignorées produisent un comportement erroné sur des chemins de code que les tests couvrent rarement ; la défaillance apparaît en production, pas à la compilation.
  • Sécurité / chaîne d'approvisionnement. Un nom de paquet halluciné est une cible d'enregistrement : les attaquants publient des logiciels malveillants sous le nom prédit, de sorte que le prochain développeur qui accepte la suggestion l'installe — l'attaque slopsquatting (terme forgé par Seth Larson de la PSF). La variante d'obsolescence réintroduit silencieusement des API dépréciées ou porteuses de CVE.
  • Charge de revue. Un code plausible reporte le fardeau sur les relecteurs, qui doivent vérifier chaque appel inhabituel dans la documentation ; une prose fluide rend cette vérification moins probable.
  • Accumulation de dette technique. Les développeurs collent souvent le stub halluciné « presque fonctionnel » et bricolent autour plutôt que de corriger l'appel à la racine — alimentant la tendance plus large de l'ère IA : hausse du copier-coller et baisse de la refactorisation (GitClear 2025 : clones multipliés par ~8×, lignes déplacées par refactorisation passées de 25 % à <10 %). Ce pattern est désormais répertorié parmi les code smells spécifiques à l'IA (arXiv 2509.20491).

##Treatment

Tactiques de processus & de prompting

  • Ancrez le modèle dans des surfaces réelles. Collez les vrais stubs de types, la page de documentation pertinente ou la source de la version installée dans le contexte, ou utilisez un outil de récupération de documentation (style Context7 / RAG). Indiquez-lui les versions exactes des dépendances issues de votre fichier de verrouillage.
  • Exigez des citations. Demandez au modèle de nommer l'entrée de documentation officielle ou la signature de type pour chaque appel tiers qu'il utilise. Règle empirique des praticiens : chaque appel de méthode sur une bibliothèque tierce doit être retracé jusqu'à son entrée de documentation avant l'approbation de la PR.
  • Faites-le tourner, dans la boucle. Exigez que tsc / mypy / pylint, le build et la suite de tests passent, et faites en sorte que l'agent exécute réellement npm install / pip install pour qu'un paquet halluciné échoue tôt plutôt que d'atteindre la revue.
  • Demandez-lui de réutiliser, pas d'inventer. Donnez-lui un grep du module existant et demandez-lui d'appeler les helpers existants (réutilise les helpers de utils/http.ts) au lieu d'en conjurer de nouveaux — cela contre aussi le smell connexe de duplication par helper réinventé.
  • Verrouillez les dépendances. Utilisez un fichier de verrouillage + une liste blanche d'installation et un scanner de chaîne d'approvisionnement (Socket/Snyk) avant l'ajout de tout nouveau paquet, afin que des noms slopsquattés ne puissent pas se glisser.

Le refactoring du code

Remplacez l'appel inventé par le véritable, vérifié. Si vous voulez vraiment la commodité que le modèle a imaginée, implémentez-la une seule fois contre l'API réelle derrière un wrapper Extraire une fonction au lieu de disperser l'appel fictif.

// Avant — paramètre halluciné + forme de SDK mélangée
async function refundLast(chargeId: string) {
  // `stripe.charges.refund` et cette forme d'option n'existent pas
  return stripe.charges.refund(chargeId, { amount: 500, reason: 'requested' });
}

// Après — vérifié contre les types/docs du SDK Stripe installé,
// et la « commodité » encapsulée une fois pour ne pas répéter la vraie API
async function refundCharge(chargeId: string, amountCents: number) {
  return stripe.refunds.create({
    charge: chargeId,
    amount: amountCents,
    reason: 'requested_by_customer',
  });
}

Pour la variante d'obsolescence, traitez un appel déprécié signalé comme une véritable tâche de mise à niveau : passez à l'API actuelle et épinglez la version, au lieu de faire taire l'avertissement.

Limites. Les vérificateurs de types et les résolveurs attrapent le sous-ensemble résoluble (objets typés, imports non résolus). Le reste dynamique/non typé — options inventées sur any, clés de configuration en chaînes, champs de payload REST — n'a aucun détecteur automatisé fiable et doit être vérifié par un humain contre la vraie documentation.

##Detected by