The 5 Most Common AI Coding Mistakes That Crash Production
AI coding assistants are incredible at turning ideas into working prototypes, but they make predictable mistakes that only surface in production. Missing dependencies, hardcoded localhost URLs, strict build failures, missing environment variables, and broken Dockerfiles are the five failure modes that account for the vast majority of AI-generated app crashes. If you have ever deployed a Cursor or Lovable app and watched it fail, one of these five was almost certainly the cause. Here is a field guide to all five, why they happen, and how to catch them before they crash your production deployment.
The direct answer is that these five mistakes are not random. They are structural side effects of how LLMs generate code. Each one has a known root cause, a known failure mode, and a known fix. The problem is that vibe coders encounter them one at a time, debug each one manually, and never build a mental model of the pattern. This article gives you that mental model, so you can recognize the failure modes instantly and apply the fixes systematically instead of debugging from scratch every time.
A note on scope: these five are not the only mistakes AI assistants make. They are the five that account for the bulk of deployment failures. Other mistakes (logic bugs, security vulnerabilities, performance regressions) exist and matter, but they are harder to detect automatically and require human review. The five in this article are the boring, repetitive, machine-detectable failure modes that a platform can and should catch for you.
Mistake 1: Missing Dependencies in package.json
The most common AI coding mistake is importing packages without adding them to package.json. Cursor, Lovable, and Bolt.new all do this regularly. The LLM writes import clsx from 'clsx' confidently, because clsx appears in its training data constantly, but it does not update package.json or run npm install. Locally, this works if you happen to have clsx installed from a previous project. In a fresh Docker build on a cloud provider, the package is missing and the build fails with Cannot find module 'clsx'.
The fix at the platform level is what Deployxa's AutoRepairService does: trap the build failure, identify the missing package from the stderr, inject it into package.json, clean the lockfile, and retry the build. Up to two retry attempts handle the common case where multiple packages are missing. The repair is logged transparently, so you can see what was added and review the change before merging it into your main branch.
To catch this manually, run npm install --dry-run before pushing, or use a tool like depcheck to find imports that are not in your dependency list. But the platform-level fix is more reliable, because it catches packages the LLM adds in future edits, not just the ones present at commit time.
The Packages Most Frequently Missing
Based on AutoRepairService telemetry across thousands of builds, the top 10 most-frequently-missing packages in AI-generated apps are:
- clsx (className composition)
- lucide-react (icons)
- tailwind-merge (className deduplication)
- framer-motion (animations)
- zod (schema validation)
- react-hook-form (form state)
- @hookform/resolvers (Zod + react-hook-form adapter)
- @radix-ui/react-dialog (modal primitive)
- @radix-ui/react-slot (composition primitive)
- sonner (toast notifications)
If your AI-generated app uses any of these, double-check that each is in your package.json before pushing. Better yet, let the AutoRepairService handle it.
Mistake 2: Hardcoded Localhost URLs
The second most common mistake is hardcoded http://localhost:3000 or http://127.0.0.1:8000 URLs in client-side fetch calls. The LLM writes these because they dominate its training data (every React tutorial uses them). On your machine, they work because your dev server is listening. In production, they fail with ERR_CONNECTION_REFUSED, because the browser is running on your user's machine, not yours.
The fix at the platform level is Deployxa's proactive localhost rewriter: scan .ts, .tsx, .js, .jsx, .vue, and .svelte files for localhost URLs, and rewrite them to relative paths (/api/...) before the build starts. The rewrite is logged, and your source repository is not modified.
To catch this manually, search your codebase for localhost and 127.0.0.1 before pushing. Replace each instance with an environment variable reference (process.env.NEXT_PUBLIC_API_URL). But this is tedious and error-prone, because the LLM might add new localhost URLs in future edits. The platform-level fix is more reliable.
The Variants of the Localhost Trap
The trap has several variants worth knowing. First, the explicit fetch: fetch('http://localhost:3000/api/users'). The rewriter catches this. Second, the template literal: ` fetch(http://localhost:3000/api/users/${id}) . The rewriter catches this. Third, the axios instance: axios.defaults.baseURL = 'http://localhost:3000'. The rewriter catches the assignment, but subsequent axios.get('/api/users') calls already use relative paths and are not touched. Fourth, the WebSocket: new WebSocket('ws://localhost:3000/socket'). The rewriter does not catch ws:// URLs by default, because WebSockets in production often need a different scheme (wss://) and a different host (a dedicated WebSocket server). You must handle these manually via environment variables. Fifth, the server-side call: fetch('http://localhost:3000/api/internal', { cache: 'no-store' })` inside a Next.js server action. The rewriter leaves this alone, because server-side code in a single-container deployment can legitimately reach itself via localhost.
Mistake 3: Strict ESLint and TypeScript Build Failures
The third mistake is not really a mistake in the code, but a mistake in the build configuration. Next.js 15 enables strict ESLint and TypeScript checking during production builds by default. Any warning becomes an error. For hand-written code reviewed by experienced engineers, this is reasonable. For AI-generated code that was never linted or type-checked in a clean environment, it is a deployment blocker. A single unused variable or implicit any can abort the entire build.
The fix at the platform level is Deployxa's build resilience injector: detect Next.js projects, and inject eslint: { ignoreDuringBuilds: true } and typescript: { ignoreBuildErrors: true } into next.config.js before the build starts. The injection is logged, and your source repository is not modified.
To catch this manually, add the same flags to your next.config.js yourself. But again, the platform-level fix is more reliable, because it applies automatically to every Next.js project you deploy, without you having to remember to configure it.
The Specific Errors That Kill Builds
The most common TypeScript errors that abort AI-generated Next.js builds are:
- TS2322: Type 'string | undefined' is not assignable to type 'string' (from noUncheckedIndexedAccess strict mode)
- TS6133: 'x' is declared but its value is never read (unused variable)
- TS7006: Parameter 'x' implicitly has an 'any' type (missing type annotation)
- TS2345: Argument of type 'string' is not assignable to parameter of type 'Foo' (type mismatch)
- TS2769: No overload matches this call (overload resolution failure)
The most common ESLint errors are:
- @typescript-eslint/no-unused-vars
- react/no-unescaped-entities
- @next/next/no-img-element
- react-hooks/exhaustive-deps
- @next/next/no-html-link-for-pages
Each of these is a one-line fix in the code, but chasing them across hundreds of files is hours of work. The injector bypasses all of them at once.
Mistake 4: Missing Environment Variables
The fourth mistake is forgetting to configure environment variables in production. The LLM generates code that reads process.env.DATABASE_URL, and locally you have a .env file that provides it. But .env files are gitignored and do not travel to production. The first deployment crashes on boot with PrismaClientInitializationError: Environment variable not found: DATABASE_URL or a similar error.
The fix at the platform level is Deployxa's pre-flight scanner: inspect the repository for known patterns that require environment variables (Prisma schemas, NextAuth configs, Stripe integrations), and warn about missing variables before the build starts. The scanner provides templates for common connection string formats, so you can add the variable quickly without looking up the syntax.
To catch this manually, make a checklist of every environment variable your app needs, and verify each one is configured in your cloud provider's dashboard before deploying. But this is manual work that is easy to forget, especially for vibe coders who do not have a deployment checklist habit. The platform-level fix is more reliable.
The Most Commonly-Missing Variables
Based on pre-flight scanner telemetry, the top 10 most-frequently-missing environment variables are:
- DATABASE_URL (Prisma, Drizzle, raw Postgres)
- NEXTAUTH_SECRET (NextAuth)
- NEXTAUTH_URL (NextAuth)
- STRIPE_SECRET_KEY (Stripe)
- STRIPE_WEBHOOK_SECRET (Stripe webhooks)
- RESEND_API_KEY (Resend email)
- UPSTASH_REDIS_REST_URL (Upstash Redis)
- UPSTASH_REDIS_REST_TOKEN (Upstash Redis)
- OPENAI_API_KEY (OpenAI)
- ANTHROPIC_API_KEY (Anthropic)
If your app uses any of these libraries, the scanner will flag the missing variable before the build runs.
Mistake 5: Hand-Written Dockerfiles That Fail
The fifth mistake is asking the LLM to write a Dockerfile and then watching it fail. AI-generated Dockerfiles are unreliable because they are tightly coupled to the target environment in ways the LLM cannot fully know. A Dockerfile that works on Fly.io might fail on Render because of a different glibc version. A Python Dockerfile that works on Railway might fail on AWS App Runner because of a missing system library. The error messages are cryptic (libstdc++.so.6: cannot open shared object file, permission denied, segmentation fault), and debugging them can take hours.
The fix at the platform level is Deployxa's zero-config engine: detect the framework from package.json or other manifest files, generate the correct internal build configuration, and never expose you to hand-written Dockerfiles. For the 95 percent of web applications that fit standard frameworks (Next.js, Vite, React, FastAPI, Django, Laravel, Go), the zero-config engine handles containerization entirely. For the 5 percent with genuine edge cases (custom system dependencies, unusual runtimes), you can provide a Dockerfile and Deployxa will use it.
To catch this manually, delete your Dockerfile and let the platform generate one. If you genuinely need a custom Dockerfile, test it locally with docker build and docker run before pushing. But for most apps, the zero-config approach is faster and more reliable.
The Dockerfile Patterns Most Likely to Fail
The most common AI-generated Dockerfile patterns that fail in production are:
- Alpine base images with native npm modules (Sharp, Bcrypt, node-canvas all fail on musl libc)
- Multi-stage builds that copy node_modules from a builder stage with a different Node version than the runner
- COPY . . before RUN npm ci, which invalidates the Docker layer cache on every code change
- Missing ca-certificates in the runtime stage, which causes HTTPS calls to fail with UNABLE_TO_VERIFY_LEAF_SIGNATURE
- Running as root, which Cloud Run and some other platforms reject
- Missing EXPOSE directive, which causes port binding failures on platforms that auto-detect the port
The zero-config engine handles all of these correctly by default. If you must write your own Dockerfile, audit it against this list before pushing.
The Pattern: Platform-Level Fixes for AI Coding Mistakes
The unifying insight is that all five of these mistakes are predictable, structural side effects of AI-assisted development. No amount of prompting will fully eliminate them, because they flow from how LLMs generate code. The right solution is to handle them at the platform level, so the vibe coder never has to think about them. Deployxa's auto-healing stack does exactly this:
AutoRepairService -> catches missing dependencies
Localhost rewriter -> fixes hardcoded URLs
Build resilience -> bypasses strict ESLint/TypeScript
Pre-flight scanner -> warns about missing env vars
Zero-config engine -> eliminates hand-written DockerfilesEach of these systems is bounded, transparent, and logged. They do not modify your source repository. They only handle the specific failure modes they were designed for. Together, they form a safety net that catches the most common AI coding mistakes and fixes them automatically, so you can focus on building the product instead of debugging the deployment.
Step-by-Step: A Pre-Deployment Checklist for AI-Generated Apps
If you are deploying to a platform without auto-healing, here is a manual checklist to catch all five mistakes before they crash production.
Step 1: Check for missing dependencies
Run npx depcheck to find imports that are not in your package.json. Install any missing packages.
npx depcheck
# Output:
# Missing dependencies: clsx, lucide-react, tailwind-merge
npm install clsx lucide-react tailwind-mergeStep 2: Search for localhost URLs
Run grep -r "localhost" src/ and grep -r "127.0.0.1" src/. Replace each instance with an environment variable reference.
grep -rn "localhost\|127.0.0.1" src/ | grep -v node_modules
# Manually replace each with process.env.NEXT_PUBLIC_API_URL or a relative pathStep 3: Add build resilience flags
In your next.config.js, add eslint: { ignoreDuringBuilds: true } and typescript: { ignoreBuildErrors: true }.
Step 4: List all environment variables
Search your code for process.env. and make a list. Verify each one is configured in your cloud provider's dashboard.
grep -roh "process\.env\.[A-Z_]*" src/ | sort -u
# Output:
# process.env.DATABASE_URL
# process.env.NEXTAUTH_SECRET
# process.env.STRIPE_SECRET_KEY
# Then verify each is set in your cloud provider's dashboardStep 5: Remove hand-written Dockerfiles
If you have a Dockerfile, consider whether you actually need it. For standard frameworks, the platform's zero-config engine is more reliable.
If you are deploying to Deployxa, you can skip this checklist entirely. The auto-healing stack handles all five mistakes at the platform level.
Common Pitfalls
Three pitfalls appear even with the checklist. First, depcheck false positives. depcheck sometimes flags packages that are used implicitly (like @types/node for TypeScript types) as missing. Read its output critically. Second, the grep for localhost misses dynamically-constructed URLs. If your code does 'http://localhost:' + port, the grep finds it but the manual fix is harder, because you need to refactor to a template literal first. Third, environment variables that are required only in certain code paths. If your code reads process.env.OPTIONAL_FLAG inside an if block, it might be optional, and the checklist will flag it as missing even though the app will run without it. Use judgment: required-for-boot variables are critical; feature-flag variables are not.
Pricing Reality: The Cost of the Five-Bug Tax
Each of the five bugs has a cost when caught manually instead of at the platform level. The table below estimates the cost per bug per deployment, based on observed iteration times.
| Bug | Manual detection time | Manual fix time | Failed build cost on Vercel | Failed build cost on Deployxa |
|---|---|---|---|---|
| Missing dep | 2-5 min | 1-2 min per dep | 2-4 min build minutes per attempt | 0 (auto-repaired) |
| Localhost URL | 5-10 min | 1-3 min per URL | 1-2 min build minutes | 0 (auto-rewritten) |
| Strict build | 5-15 min | 2 min (config flag) | 2-4 min build minutes | 0 (auto-injected) |
| Missing env var | 5-15 min (after boot crash) | 2 min | 1-2 min build + boot crash | 0 (pre-flight warns) |
| Bad Dockerfile | 30-90 min | 5-30 min per iteration | 3-5 min build minutes per attempt | 0 (zero-config) |
For an AI-generated app with all five bugs, the manual cost on Vercel Hobby is roughly 90-150 minutes of developer time plus 15-30 build minutes. On Vercel Pro, add $20/month plus overages. On Deployxa, the cost is 0 developer time (auto-healed) and 0 build minutes (not metered), all included in the $9/month flat tier.
Conclusion: Stop Debugging the Same Five Bugs
The five most common AI coding mistakes are not random. They are structural, predictable, and fixable at the platform level. If you find yourself debugging the same five failure modes on every deployment, you are using the wrong platform. Deployxa's auto-healing stack catches all five automatically, so you can ship without the debug tax.
Ready to ship without the five-bug tax? Drag your project to Deployxa Drop for an instant live preview, or install the CLI with npm i -g @deployxa/cli and deploy from your terminal. For more on each specific mistake, see our articles on missing dependencies, the localhost trap, and Next.js build errors. Explore our free developer tools to speed up your workflow.