AI Code Hallucinations are false or plausible-seeming code artifacts generated by large language models—often in response to a natural language prompt—whose content, structure, or behavior is internally consistent but factually incorrect or logically unsound. They matter when developers, system architects, or teams rely on AI to generate code for production systems: from initial prototypes to full services, from API endpoints to database schemas. A hallucination is not merely a typo or a missing function—it is a convincing but incorrect piece of code that passes inspection but fails in deployment.
Generating Code from Natural Language Prompts
To generate code, engineers use a prompt that describes a system requirement, such as:
> "Create a REST API endpoint that accepts a user’s name and email, validates them, and stores them in a PostgreSQL database. Return a 201 Created response with the created user ID."
The AI model—whether hosted locally via llama-cpp, via a cloud API like OpenAI’s gpt-4o, or as a self-hosted service with vLLM—processes this prompt and returns code. The output is not just a function, but a complete, runnable module.
from fastapi import FastAPI, HTTPException, Body
import psycopg2
from pydantic import BaseModel
app = FastAPI()
class UserCreate(BaseModel):
name: str
email: str
@app.post("/users", status_code=201)
def create_user(user: UserCreate):
conn = psycopg2.connect(
host="localhost",
database="users_db",
user="admin",
password="secret"
)
cur = conn.cursor()
try:
cur.execute(
"INSERT INTO users (name, email) VALUES (%s, %s) RETURNING id",
(user.name, user.email)
)
user_id = cur.fetchone()[0]
conn.commit()
return {"id": user_id}
except Exception as e:
conn.rollback()
raise HTTPException(status_code=500, detail=str(e))
finally:
cur.close()
conn.close()
This code appears correct. But a hallucination lurks beneath: the users table does not exist, the psycopg2 connection parameters are hardcoded, and the CREATE TABLE users statement is missing. The model assumed the schema, but it did not produce it.
Recognizing Hallucinations in Context
When a developer uses git commit -m "Add user creation endpoint" after generating this code, the AI has already hallucinated the schema and the implementation, but the code fails in CI with:
psycopg2.OperationalError: relation "users" does not exist
The model hallucinated a table named users, but the actual database table is user_profiles. This is a *schema-level hallucination*. It is not just an error in the code—it is a failure in the *assumed world* that the model constructs.
To catch such failures, engineers use pytest with a conftest.py that sets up a test database:
# conftest.py
import pytest
import psycopg2
from pathlib import Path
@pytest.fixture(scope="session")
def test_db():
conn = psycopg2.connect(
host="localhost",
database="test_users_db",
user="test_user",
password="test_pass"
)
cur = conn.cursor()
cur.execute("""
CREATE TABLE user_profiles (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
)
""")
conn.commit()
yield conn
cur.close()
conn.close()
Running pytest tests/ reveals that the API endpoint creates a user in user_profiles, but the response includes {"id": 1}—a correct format, but the model hallucinated a users table. The code is correct, but the *assumed context* is wrong.
Debugging Hallucinations in CI/CD
In a CI pipeline using GitHub Actions, the following workflow.yml runs tests and builds a Docker image:
# .github/workflows/test.yml
name: Test and Build
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r tests/requirements.txt
- name: Run tests
run: pytest tests/ --cov=api --cov-report=xml
- name: Build Docker image
run: |
docker build -t user-service:latest .
docker push user-service:latest
The pytest step fails with:
E psycopg2.OperationalError: relation "users" does not exist
E LINE 1: INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id
E ^
FAILED tests/test_api.py::test_create_user
The CI system is correct. The model hallucinated a table named users, but the test database uses user_profiles. This mismatch is a *contextual hallucination*: the model assumed a global context it did not verify.
Correcting Hallucinations with Explicit Prompts
To reduce hallucinations, engineers refine the prompt to include explicit assumptions, constraints, and required artifacts. A better prompt includes:
> "Create a REST API endpoint that accepts a user’s name and email, validates them, and stores them in a PostgreSQL database. The database has a table named user_profiles with columns id, name, and email. Return a 201 Created response with the created user ID. Include the SQL script to create the table."
The AI now generates:
-- db/schema.sql
CREATE TABLE user_profiles (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);
# api/users.py
from fastapi import FastAPI, HTTPException, Body
import psycopg2
from pydantic import BaseModel
app = FastAPI()
class UserCreate(BaseModel):
name: str
email: str
@app.post("/users", status_code=201)
def create_user(user: UserCreate):
conn = psycopg2.connect(
host="localhost",
database="users_db",
user="admin",
password="secret"
)
cur = conn.cursor()
try:
cur.execute(
"INSERT INTO user_profiles (name, email) VALUES (%s, %s) RETURNING id",
(user.name, user.email)
)
user_id = cur.fetchone()[0]
conn.commit()
return {"id": user_id}
except Exception as e:
conn.rollback()
raise HTTPException(status_code=500, detail=str(e))
finally:
cur.close()
conn.close()
Now, the CREATE TABLE statement is included, and the INSERT uses the correct table name. The model has reduced its hallucination by explicitly stating its assumptions.
Detecting Hallucinations via Code Linting and Type Checking
Even with better prompts, hallucinations persist. Engineers use mypy to catch type-related errors:
# pyproject.toml
[tool.mypy]
python_version = "3.11"
strict = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
warn_unused_configs = true
Running mypy api/ reveals:
api/users.py:25: error: Argument 1 to "execute" has incompatible type "tuple[str, str]"; expected "tuple[Any, ...]"
Found 1 error in 1 file (checked 1 source file)
The cur.execute call passes a tuple of two strings, but the model expected a tuple[Any, ...]—a common mistake. The model hallucinated the signature of execute, but psycopg2 expects tuple[Any, ...] for the query parameters.
To fix this, the engineer adds type hints to the function:
cur.execute(
"INSERT INTO user_profiles (name, email) VALUES (%s, %s) RETURNING id",
(user.name, user.email) # type: tuple[str, str]
)
The model also hallucinated the psycopg2.connect parameters. The host, database, user, and password are hardcoded, but the postgresql connection string should be configurable. A better version uses environment variables:
import os
import psycopg2
conn = psycopg2.connect(
host=os.getenv("DB_HOST", "localhost"),
database=os.getenv("DB_NAME", "users_db"),
user=os.getenv("DB_USER", "admin"),
password=os.getenv("DB_PASSWORD", "secret")
)
Resolving Hallucinations with Configuration and Environment
The model now assumes that the environment variables DB_HOST, DB_NAME, DB_USER, and DB_PASSWORD are set. But in Dockerfile, the environment is not defined:
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
EXPOSE 8000
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"]
The CMD line hardcodes --host 0.0.0.0 --port 8000, but the model hallucinated the uvicorn configuration. The uvicorn command expects --host and --port, but the model did not include a uvicorn-config.yaml.
The engineer adds:
# uvicorn-config.yaml
host: 0.0.0.0
port: 8000
workers: 4
log-level: info
And updates the CMD:
CMD ["uvicorn", "api.main:app", "--config", "uvicorn-config.yaml"]
Now, the service starts with correct configuration, but the model still hallucinated the workers and log-level settings.
Handling Hallucinations in Production Deployment
In production, the service runs via systemctl:
# /etc/systemd/system/user-service.service
[Unit]
Description=User Service
After=network.target
[Service]
Type=simple
User=app
WorkingDirectory=/app
ExecStart=/app/venv/bin/uvicorn api.main:app --config uvicorn-config.yaml
Restart=always
EnvironmentFile=/etc/environment
[Install]
WantedBy=multi-user.target
But the EnvironmentFile is missing. The DB_HOST and DB_USER are not available. The deployment fails with:
psycopg2.OperationalError: could not connect to server: No such file or directory
Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
The model hallucinated a local PostgreSQL server listening on /var/run/postgresql/.s.PGSQL.5432, but the DB_HOST was set to db.internal in the environment.
The solution is to create /etc/environment:
# /etc/environment
DB_HOST=db.internal
DB_NAME=users_db
DB_USER=app_user
DB_PASSWORD=secure_pass
LOG_LEVEL=info
And update the systemd service to use EnvironmentFile:
[Service]
EnvironmentFile=/etc/environment
Now, the service starts correctly, and the model’s hallucinations are resolved.
Common Failure Modes and Pitfalls
- Assumed Schema: The model assumes a database schema but does not generate it. The
CREATE TABLEstatement is missing, or the column names differ from the actual schema. - Hardcoded Values: Connection strings, URLs, and paths are hardcoded but should be configurable. The model forgets to use environment variables.
- Missing Configuration: The model generates code but omits configuration files for tools like
uvicorn,nginx,celery, orkafka. - Incorrect Data Types: The model uses
intforidbut the database usesbigint. It assumesTEXTfornamebut the table usesVARCHAR(255). - Unnecessary Dependencies: The model adds
pydanticandpsycopg2but does not includefastapioruvicorninrequirements.txt. - Misplaced Logic: The model places validation logic in the wrong layer—e.g., validating input in the database layer but not in the API layer.
The Cost of Hallucinations
A hallucination silently passes review, but fails in production. The cost is not just in debugging, but in *unanticipated complexity*. A well-structured, clean codebase is built on a false premise. The model’s assumptions become the system’s constraints, but they are not documented, tested, or deployed. When the team discovers the mismatch, they must:
- Add missing schema migrations
- Write configuration documentation
- Update deployment scripts
- Add monitoring and alerts for the expected assumptions
Each hallucination adds a layer of hidden complexity—layers that were never part of the original design, yet are essential to the system’s operation.
Summary
AI Code Hallucinations are not just errors in code—they are *assumptions that are not validated*. They arise when models generate code based on implicit context, but that context is not explicitly captured. Engineers must:
- Write detailed, explicit prompts
- Include required artifacts (SQL, config, environment)
- Use linting, type checking, and testing to detect mismatches
- Deploy with full configuration, not just code
- Monitor the assumptions—what the model assumed but the system did not provide
The most effective way to reduce hallucinations is to make the assumptions *first-class citizens* in the system: documented, tested, and monitored.
This page was rewritten on 11 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.