Reduce Hallucinations in AI-Generated Code: A Review Checklist

Spot and fix AI code hallucinations before they ship with a five-point review checklist that catches invented APIs, fake imports, and confident wrong answers.

Author:
Codapress Publishing
Date:

AI coding tools are extraordinarily good at sounding confident. When they generate code that looks plausible but does not work, the model is not lying. It is hallucinating: producing output that matches the statistical patterns of correct code without implementing a correct solution.

A 2024 study found ChatGPT answered 52% of Stack Overflow questions incorrectly, delivering wrong answers with confident-sounding phrasing (source: Communications of the ACM). For generated code, the stakes are higher — a hallucinated function call compiles fine but silently corrupts data until production.

What does an AI code hallucination look like?

Hallucinations fall into recognisable patterns. Once you know what to look for, you start seeing them in almost every long AI-coding session.

TypeExampleWhy it looks real
Invented APIfetchUsers() called with an argument that does not exist in the library docsThe method name sounds plausible, and the model uses it consistently
Imaginary importfrom pipeline.tasks import run_etl where pipeline is not installedThe module name follows naming conventions the model has seen in training
Synthetic edge-case handlingA try-except that catches DatabaseTimeoutError — a class that does not exist in the driverThe error name follows a realistic pattern
Confident wrong logicAn optimisation that claims O(log n) performance but actually iterates every rowThe algorithm description matches the right big-O for a different approach
Hallucinated configurationA docker-compose.yml service name that no official image publishesThe image name is consistent with the naming pattern of real images

The five-point review checklist

Read every AI-generated block against these five checks before you commit.

1. Verify every import and dependency

The model is likelier to hallucinate a library name than you think. Before you run any AI-generated code, check that every import resolves to a real package or built-in module.

# The AI generated this — does cachetools exist on PyPI?
from cachetools import LRUCache

# Quick check in your terminal:
# pip install cachetools

If an import does not exist on PyPI, npm, or your language’s package registry, the model most likely invented it. Replace it with a real alternative or implement the feature manually.

2. Cross-reference every API call

When the model writes something like response = client.query(embedding=vector, top_k=5), check the library documentation — not the model’s memory — for the actual parameter names.

I have code that calls client.query() with a parameter called top_k. I am using the Pinecone Python SDK version 4.1. Check whether top_k is a valid parameter for the query() method. If it is not, tell me the correct parameter name and show the fix.

Provide your answer as a yes-or-no with the evidence from the docs.

A prompt like this forces the model to reveal the source of its knowledge. If it cannot cite a specific version of the docs, treat the API call as suspect and verify it yourself.

3. Run the code path, not just the happy path

AI models train on code that mostly works — they are optimised for the common case. This means they skip error handling, miss edge cases, and assume inputs are well-formed.

Test scenarioWhat the model usually writesWhat it misses
Empty arrayProcess every elementIndexError or incorrect aggregate
Null inputAssume a value existsNullPointerException
Network failureCall the API onceNo retry or backoff
Malformed inputParse successfullyNo validation or sanitisation
Concurrent accessExecute sequentiallyRace conditions

For each function the model writes, add a test for at least two of these scenarios. If the model did not handle them, you have caught a hallucination-by-omission — code that works under ideal conditions but fails everywhere else.

4. Check for invented error classes

Models frequently invent exception classes that sound realistic. A try-except block that catches DatabaseTimeoutError is almost certainly hallucinated unless you recognise it from the specific driver you are using.

The fix is to check the library’s exception hierarchy. Most well-documented libraries list their custom exceptions in a single page. If the class is not there, change the catch to a standard exception or handle the failure mode differently.

5. Trace the data flow end to end

The most subtle hallucinations happen in the middle layers of a pipeline. The model generates a transformation function that looks correct in isolation but silently drops rows, misaligns column indices, or assumes sorted data where none exists.

Trace the following data flow step by step and tell me where data could be lost or corrupted.

[Paste the relevant functions here]

For each risk you identify, suggest a guard (assertion, type check, or test) that would catch it during development.

This prompt treats the model as a code reviewer for its own output — a pattern that catches many hallucinations before they become bugs.

When the model invents an API

Here is a concrete example. A developer asked an AI assistant to write a script that batches API requests using concurrent.futures. The model produced this:

import asyncio
from aiohttp import ClientSession, ClientTimeout

async def fetch_all(urls, max_concurrent=5):
    semaphore = asyncio.Semaphore(max_concurrent)
    timeout = ClientTimeout(total=30)

    async with ClientSession(timeout=timeout) as session:
        tasks = [fetch_one(session, url, semaphore) for url in urls]
        return await asyncio.gather(*tasks)

The code looks correct. It uses asyncio, aiohttp, a semaphore for concurrency control — everything a Python developer would expect. The hallucination is invisible: aiohttp’s ClientSession does not accept a timeout parameter at the session level in the version the developer had installed. The parameter belongs on individual requests.

The fix is small, but it illustrates the pattern: the model used the right vocabulary and idiom — except for one parameter that does not exist in the real library. Without the review checklist, this code fails with a cryptic TypeError.

For a deeper guide on structuring AI coding sessions, see Harness Engineering.

Build review into your workflow

Add these habits to your regular practice:

  1. Never trust a first draft. Treat the first output as a starting point, not a finished product.
  2. Review in layers. Check imports first, then API calls, then error handling, then data flow.
  3. Run tests before you commit. If the model did not write tests, write at least one. It is your second pair of eyes.
  4. Ask the model to review itself. Prompt it to check its own code for invented APIs, fake imports, and hallucinated error classes.
  5. Keep a hallucination log. Note which patterns your model tends to produce. Some invent npm packages; others invent CSS properties. Knowing the weak spots makes review faster.

Trust but verify

AI coding tools are transformative, but they are also probabilistic engines that optimise for plausible output, not correct output.

The five-point checklist — verify imports, cross-reference APIs, test edge cases, check error classes, trace data flow — turns review from vague anxiety into a repeatable process. Apply it to every generated block to catch the hallucinations that look real and ship with more confidence.

For the full review pipeline from prompt design to production deployment, see Vibe Coding Pro.

More insights

All Articles