DEV Community

joshua dyson
joshua dyson

Posted on

Preventing Hallucinated Package Dependencies in AI-Generated Code: A Practical Guide

AI coding assistants are remarkably good at generating boilerplate, tests, and even complete features. But every now and then, they'll confidently import a package, function, or API that simply doesn't exist.

These "hallucinated dependencies" can waste debugging time, introduce supply chain risks, and even make it into pull requests if nobody notices.

This tutorial walks through a practical workflow to catch these issues automatically before they reach production.

We'll build a simple CI workflow that:

Detects missing or invalid dependencies
Verifies package installation
Scans for typosquatting risks
Runs dependency and security checks
Fails the pull request automatically when something looks suspicious

Everything uses standard tooling that you can add to an existing GitHub repository.

What Is a Hallucinated Dependency?

Suppose you ask an AI assistant to build a feature.

It returns something like this:

import { SmartCache } from "fast-cache-ai";

const cache = new SmartCache();

Looks reasonable.

Except...

fast-cache-ai doesn't exist.

Sometimes AI invents:

Package names
Functions
SDKs
API endpoints
Configuration options

The generated code looks convincing enough that developers often don't notice until CI fails—or worse, until someone tries to publish or deploy it.

Why This Matters

Beyond broken builds, hallucinated dependencies can create security problems.

Imagine an attacker publishing a package with the same hallucinated name.

If your build installs it automatically, you've just created a potential software supply chain risk.

That's why validating dependencies should be part of every AI-assisted development workflow.

Step 1: Install Dependencies from the Lock File

Always prefer deterministic installs.

For Node.js:

  • name: Install packages run: npm ci

Avoid:

  • run: npm install

Using the lock file ensures everyone—and your CI system—is installing exactly the same dependency versions.

Step 2: Verify Package Availability

A simple validation step can prevent many mistakes.

npm view express version
npm view react version

If the package doesn't exist, the command exits with an error.

For Python:

pip index versions requests

For Go:

go list -m all

These checks are lightweight and easy to automate.

Step 3: Enable Dependency Review

GitHub's Dependency Review Action helps identify risky dependency changes in pull requests.

name: Dependency Review

on:
pull_request:

jobs:
dependency-review:
runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4

  - uses: actions/dependency-review-action@v4
Enter fullscreen mode Exit fullscreen mode

This highlights newly introduced dependencies before they're merged.

Step 4: Scan for Vulnerabilities

After validating dependencies, scan them.

Example using npm:

npm audit

Or:

npm audit --audit-level=high

For Python:

pip-audit

Security scanning won't catch hallucinations directly, but it helps identify risky packages before deployment.

Step 5: Detect Typosquatting

Hallucinations sometimes resemble legitimate packages.

For example:

expressx
react-core
lodashjs
fast-cache-ai

A simple review process should flag packages that:

Are newly introduced
Have very few downloads
Have recently been published
Closely resemble well-known packages

Even a manual review of new dependencies adds an extra layer of protection.

Step 6: Add an Automated CI Check

Here's a minimal GitHub Actions workflow:

name: Validate Dependencies

on:
pull_request:

jobs:
validate:
runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4

  - uses: actions/setup-node@v4
    with:
      node-version: 20

  - run: npm ci

  - run: npm audit --audit-level=high

  - run: npm test
Enter fullscreen mode Exit fullscreen mode

If dependency installation fails, the pull request never reaches production.

Example Repository Structure

example-app/

├── .github/
│ └── workflows/
│ └── dependency-check.yml

├── package.json
├── package-lock.json
├── src/
├── tests/
└── README.md

This keeps validation close to the code and makes it easy for contributors to understand the workflow.

Try It Yourself

To see the workflow in action:

Create a simple Node.js application.
Add the GitHub Actions workflow above.
Introduce a fake package into package.json (for example, "fast-cache-ai": "^1.0.0").
Open a pull request.
Watch the workflow fail during dependency installation.

It's a simple exercise, but it demonstrates how automated validation can catch AI-generated mistakes before they become production issues.

Additional Best Practices

A few habits can significantly reduce dependency-related issues:

Review every new dependency in a pull request.
Prefer well-maintained, widely adopted packages.
Commit lock files.
Enable automated dependency updates.
Run security scans in every CI pipeline.
Treat AI-generated imports the same way you treat manually written code—verify them before trusting them.

AI should accelerate development, not replace engineering judgment.

Final Thoughts

Hallucinated dependencies aren't a flaw unique to any one AI coding assistant—they're a natural consequence of language models generating plausible-looking code.

The good news is that they're also one of the easiest AI-related risks to mitigate.

A few automated checks in your CI pipeline can catch missing packages, identify suspicious dependency changes, and stop broken pull requests long before they reach production.

As AI becomes a routine part of software development, building lightweight validation into your workflow is no longer just a nice-to-have. It's part of writing secure, reliable software.

Top comments (0)