
Please note this is AI generated content, that was manually queried, and accuracy is not guaranteed. So please read at your own risk. Hopefully it has some useful info, like researching it yourself.
🧨 Introduction
In Parts 1 and 2, we explored what AI coding tools like ChatGPT, Copilot, and CodeWhisperer can do—and how they can boost productivity, accelerate prototyping, and support development teams.
But now it’s time for a reality check.
AI doesn’t understand code like humans do. It’s not sentient. It doesn’t debug. And it certainly doesn’t know your business, product, or edge cases.
In this article, we dive deep into the risks, mistakes, limitations, and hazards of relying on AI-written code—especially in web development and software engineering.
We’ll share actual code examples, compare them to human-written alternatives, and analyze where AI breaks down—and why.
✅ Coming Up:
Part 1: What Can AI Really Do in Software Engineering?
→ Capabilities, current state, and boundaries of AI in code generation
Part 2: The Advantages of AI-Written Code
→ Efficiency, speed, cost-saving, and accessibility
Part 3: The Dark Side of AI-Generated Code
→ Common errors, hallucinations, and security flaws
Part 4: Human vs AI Code — What the Future Holds
→ Direct comparisons, strengths, limitations, and the hybrid future
💣 1. Hallucinated APIs and Non-Existent Methods
LLMs predict text based on training data. This often leads to hallucination—fabricating functions, classes, or methods that don’t exist.
🔴 Example 1: Mongoose “Magic” Method
Prompt:
“Get a user by email in Mongoose.”
AI Output:
User.findByEmail('[email protected]');
Reality:
❌ There is no built-in findByEmail() in Mongoose unless manually defined.
✅ Correct Version:
User.findOne({ email: '[email protected]' });
⚠️ Consequence:
Silent failure or runtime errors. Worse—junior devs may not know it’s incorrect.
🔴 Example 2: Fabricated Browser APIs
Prompt:
“Detect dark mode in JavaScript.”
AI Output:
if (window.getDarkMode()) {
console.log('Dark mode is enabled');
}
❌ window.getDarkMode() does not exist.
✅ Correct Version:
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
console.log('Dark mode is enabled');
}
🕳 2. Superficial Business Logic (Not Domain-Aware)
AI can write generic functions, but it doesn’t understand business rules unless explicitly described.
🔴 Example 3: Subscription Billing
Prompt:
“Apply a 10% discount to all premium users.”
AI Output:
if (user.isPremium) {
price = price * 0.9;
}
Hidden Problems:
- What if price is in different currencies?
- Are taxes applied before or after discount?
- Are discounts stackable?
- Is the user on a trial?
🧠 A human developer would ask these questions. AI won’t unless you write a 10-paragraph prompt.
🔓 3. Critical Security Oversights
AI often misses security best practices, especially for:
- Input validation
- Authentication flows
- Access control
- CSRF/XSS protection
🔴 Example 4: Plaintext Password Comparison
Prompt:
“Create a login endpoint with Node.js and MongoDB.”
AI Output:
if (user.password === req.body.password) {
// login
}
🚨 Danger: Plaintext password comparison is a massive security flaw.
✅ Correct Approach:
const bcrypt = require('bcrypt');
const match = await bcrypt.compare(req.body.password, user.passwordHash);
🔴 Example 5: No Authorization Check
Prompt:
“Update a user profile.”
AI Output:
router.put('/user/:id', async (req, res) => {
await User.updateOne({ _id: req.params.id }, req.body);
res.send('OK');
});
🚨 No check to see who is making the request. Anyone could update any user’s data.
🧠 A human would add:
if (req.user.id !== req.params.id) return res.status(403).send('Unauthorized');
📉 4. Overconfidence and Hidden Errors
AI-generated code often looks perfect—but is subtly wrong.
🔴 Example 6: Broken Regex
Prompt:
“Write a regex to validate an email.”
AI Output:
const regex = /^\w+@\w+\.\w+$/;
Looks fine, right?
❌ But It Fails On:
[email protected](valid)[email protected](valid)
✅ Safer Option:
Use a well-tested library like validator.js:
const validator = require('validator');
validator.isEmail(email);
🔁 5. Repetition Without Understanding
AI often reuses patterns—even when inappropriate.
🔴 Example 7: Misused HTTP Status Code
res.status(500).send('User not found');
❌ HTTP 500 = Server Error. A missing user should return 404.
🧠 Human fix:
res.status(404).send('User not found');
🛑 6. Error Handling is Often Missing or Wrong
🔴 Example 8: Missing Try/Catch Block
const user = await User.findById(id);
res.json(user);
If findById fails or returns null? ❌ Crash or null ref.
✅ Corrected:
try {
const user = await User.findById(id);
if (!user) return res.status(404).json({ error: 'User not found' });
res.json(user);
} catch (err) {
res.status(500).json({ error: 'Server error' });
}
🧪 7. Misleading Test Coverage
AI writes syntactically valid tests—but they’re often shallow or unrealistic.
🔴 Example 9: Trivial Test Cases
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
✅ It passes—but tells you nothing about:
- Negative numbers
- Edge cases
- Floating point errors
- Overflow
📦 8. Code Bloat and Inefficiency
Sometimes, AI produces verbose or inefficient code when a cleaner solution exists.
🔴 Example 10: Manual Loop Instead of Built-in Function
let sum = 0;
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
}
✅ Better:
const sum = arr.reduce((a, b) => a + b, 0);
AI doesn’t always know your team’s style guide or performance goals.
🛠 9. Not Reusable or Modular by Default
AI often writes single-use code that isn’t DRY or reusable.
🔴 Example 11: Hardcoded Logic
function sendWelcomeEmail(user) {
const email = user.email;
// hardcoded subject, body
}
Better version would extract templates, use config, support localization, etc.
⚖️ 10. AI Code vs Human Code (Side-by-Side)
| Scenario | AI Code Example | Human Fix or Improvement |
|---|---|---|
| Password login | user.password === input | Use bcrypt.compare() |
| API method | User.findByEmail() | Replace with findOne({ email }) |
| Status codes | res.status(500).send('Not found') | Use 404 |
| Test coverage | Simple success test only | Add edge, failure, and negative test cases |
| Error handling | No try/catch | Wrap in try/catch with 500 fallback |
| Auth checks | Anyone can update any profile | Check req.user.id === req.params.id |
| Regex for email | ^\w+@\w+\.\w+$ | Use validated library like validator.js |
| Loops vs built-ins | for loop for sum | Use reduce() |
🧠 Why AI Makes These Mistakes
- Lack of real-world context
- Trained on public code (which may be flawed)
- Predicts next token, not program behavior
- Doesn’t test or run code
- Not aware of company-specific rules, business logic, or APIs
🚨 When AI-Generated Code Can Be Dangerous
- Authentication systems
- Payment processors
- Healthcare apps (HIPAA/GDPR)
- Security libraries
- Anything regulated or legally liable
Use AI to support, not build these systems.
✅ Best Practices When Using AI Code Tools
| Tip | Why It Matters |
|---|---|
| Always review AI-generated code | Catch hallucinations, security flaws |
| Use AI for draft code, not prod | Reduces risk |
| Add comments to AI prompts | Improves context and output quality |
| Treat AI like a junior dev | Needs supervision and correction |
| Pair AI code with linters/tests | Strengthen safety net |
💬 Final Thoughts
AI coding tools are powerful allies—but not autonomous developers.
Treat AI like a super-smart autocomplete, not an infallible engineer. If you wouldn’t deploy code written by a brand-new intern without review, don’t do it with AI code either.
📚 Sources & Further Reading
- GitHub Copilot Safety Guide
- Stanford Code LLM Hallucinations Study
- OWASP Top 10: Common Web Security Risks
- AI Code Generation Benchmarks (HumanEval)
- Bugs Introduced by AI (Arxiv Study)
🔜 Next Up:
Part 4: Human vs AI Coding – What the Future Holds
→ Will AI replace developers? What will hybrid development look like in 5 years?
Source: ChatGPT
