Step-by-step guides for the most common Claude Code problems, written by real developers.
@NotNull, @NotBlank, @Size and other validation annotations are added to bean fields but validation never executes. Invalid data passes through without error. Validation was added but not wired up properly.
Annotations exist but validator isn't invoked on bean creation or API calls.
API has no rate limiting. Malicious users can spam endpoints with thousands of requests, causing DoS attack. Legitimate requests are throttled. API was designed but rate limiting was deferred as 'optimization' and never implemented.
No mechanism exists to slow down or reject excessive requests from single client.
Frontend makes a complex request (POST with JSON body) to API, preflight OPTIONS request fails with 403 or 405 error. Actual request never sent because browser stops at preflight check. Simple GET requests work but POST/PUT/DELETE fail.
CORS configuration exists but doesn't handle preflight requests correctly.
Real-time features using WebSocket connections drop unexpectedly. Client loses connection to server with no reconnection attempt. Users experience gaps in real-time updates or are suddenly disconnected.
Connection works initially but doesn't handle network interruptions or server resets gracefully.
API endpoint returns data in a different structure than the frontend expects. Frontend code calls API successfully but crashes when trying to access expected properties that don't exist or are nested differently.
This common integration problem surfaces when frontend and backend are developed independently without coordinating on response format.
Frontend component was built but never connected to the actual API endpoint. The component's action buttons call mock functions or make requests to undefined URLs. Moving to production revealed that the UI flow is orphaned from backend logic.
Frontend was developed in isolation without coordinating with API development, leaving integration gaps.
Webhook endpoint receives POST requests (verified in logs) but event handlers don't execute. The webhook returns 200 OK but triggers no side effects. Events are silently dropped with no error indication, making this extremely difficult to debug.
This commonly happens when webhook routing is correct but handlers aren't invoked, or when async processing silently fails.
Stripe webhook endpoint is registered and receiving events (confirmed in Stripe dashboard) but handlers aren't executing. Payments are charged successfully in Stripe but the application doesn't record orders, send confirmations, or update inventory.
The webhook integration appears complete but events are being ignored silently.
Passwords are hashed but using a weak algorithm. Plain MD5, SHA-1, or simple salted SHA-256 is used instead of proper password hashing. Security audit flags the implementation as inadequate for protecting user credentials.
Password storage exists but doesn't use modern algorithms that resist brute-force attacks.
Application fails to start with circular dependency error. Module A imports Module B which imports Module A, creating a cycle that prevents initialization. This often surfaces after refactoring when reorganizing modules.
The error message clearly indicates a circular dependency but resolving it requires understanding module relationships.
Application has configuration file (application.yml or .env) but settings aren't being loaded. Default values are used instead, causing application to attempt connections to wrong database, wrong API endpoints, or with wrong credentials.
Configuration file exists and is readable but isn't being discovered by the application.
After successfully authenticating with OAuth during a Claude Code session, the token is lost when starting a new session. Users are forced to re-authenticate every time they run Claude Code, defeating the purpose of persistent authentication.
This commonly occurs when the agent doesn't properly serialize session state or when the token storage mechanism isn't configured for persistence across CLI invocations.
When Claude Code attempts to access a GitHub repository, it receives 403 Forbidden errors despite having a valid GitHub token. The token was generated with limited scopes and lacks permissions needed for repository operations.
This manifests when the user's OAuth flow doesn't request all necessary scopes, or when GitHub's scope requirements change but the CLI isn't updated.
Unauthenticated users can access protected endpoints that should require authentication. The auth middleware exists but doesn't actually enforce authentication checks, allowing requests to bypass security.
This typically happens when middleware is registered but improperly configured, or when certain routes are accidentally whitelisted without restriction.
CORS configured with Access-Control-Allow-Origin: * allowing any origin to access the API. Security audit flags this as a vulnerability. Any website can make requests to the API on behalf of users.
While allowing all origins is convenient for development, it's a security risk in production.
Security review discovers SQL injection vulnerability. Application constructs SQL queries by string concatenation with user input. Attacker could manipulate queries by injecting SQL code through input fields.
Query works correctly for normal input but fails to protect against malicious input.
JWT tokens are generated successfully but validation fails on subsequent requests. User logs in, receives token, but next request with the token in Authorization header is rejected. Tokens work briefly then expire or fail unexpectedly.
Token generation and validation logic both exist but something about the verification is failing.
When an operation fails partway through, previous changes aren't rolled back. Database is left in inconsistent state with partial changes. For example: charge credit card but fail to record order = customer charged but no order created.
Transaction management exists but doesn't properly rollback on all error types.
A new database migration file was created but didn't execute when starting the application. The database schema remains out of sync with the application code, causing runtime errors when trying to access new columns or tables.
This occurs when migration tools (Flyway, Liquibase) don't detect the new file, have incorrect naming conventions, or encounter permission issues during execution.
After refactoring ORM relationship configurations, related entities stopped lazy loading. Now every query that accesses relationships triggers additional database queries, causing severe N+1 query problems and timeouts.
The ORM configuration was changed to eager loading for debugging but wasn't reverted, or the lazy loading annotations were accidentally removed during refactoring.
Seed data script that populates initial test data in development is not executing. The database starts empty, causing tests and manual testing to fail. This might be a timing issue where seed data attempts to load before migrations complete.
Seed data loading is typically optional and failures are silently ignored, making this hard to debug.
Application encounters deadlock errors intermittently when multiple users perform operations simultaneously. Specific sequences of operations cause deadlock: Thread A waits for lock held by Thread B, which waits for lock held by Thread A. Application must retry deadlocked operations.
Deadlocks are hard to reproduce but fail under load testing or in production.
Application gradually exhausts Redis connection pool over hours. New connections fail with 'pool exhausted' error. Existing connections aren't being returned to the pool properly, causing connection leak.
Redis works initially but degrades as connections accumulate.
Gradle build cache contains stale artifacts from previous builds. Changes to source files aren't reflected in the compiled output, causing deploying of old code. Incremental builds work correctly, but CI/CD pipeline with partial cache hits behaves unexpectedly.
This is particularly problematic when generated code or resource files are cached but source changed.
Application fails to make HTTPS requests to external services, throwing SSL certificate validation errors. In development with self-signed certificates it works (validation disabled), but in production with proper certificates it fails.
Certificate is valid and properly installed but the application doesn't trust it.
Application is running but logging statements produce no output. Debug logs don't appear even with verbose configuration. Application logs nowhere for troubleshooting despite logging statements in code.
Logging framework is configured but output isn't being written.
CI/CD pipeline fails during build or deployment steps because required environment variables aren't available. The application starts correctly in development where variables are set locally, but fails in the pipeline with 'variable not defined' errors.
This commonly occurs when moving configuration from .env files to CI/CD secret management, or when new required variables aren't added to all environments.
Docker build succeeds locally but fails in CI/CD pipeline with dependency resolution errors. The Dockerfile installs system packages that conflict with application dependencies, or transitive dependencies pull incompatible versions.
This often only appears in CI/CD because local Docker daemon caches layers, masking the real issue.
Application attempts to write files (logs, uploads, caches) but fails with permission denied errors. The user running the application doesn't have write permissions to the target directory. Works in development where user has full permissions but fails in production.
This commonly occurs with log files, uploaded files, or temporary cache directories.
Your application continues to send emails to addresses that have previously bounced (invalid addresses, full mailboxes, blocked domains). This damages your sender reputation score, causing email providers to throttle or block all your emails, including those to valid recipients.
Without bounce handling, your deliverability degrades over time. Emails that used to reach inboxes start landing in spam, then stop arriving at all. By the time you notice, your sending domain may be blacklisted and recovery takes weeks.
The issue compounds because every failed delivery attempt further damages your reputation, creating a downward spiral that affects all your users, not just the ones with invalid addresses.
Your application's email sending suddenly stopped working. Transactional emails (password resets, order confirmations, verification emails) are no longer being delivered. The email service returns errors about deprecated endpoints, removed API versions, or unsupported authentication methods.
Email service providers regularly deprecate old API versions and authentication methods. Claude Code may have generated code using an older API version that was current at training time but has since been retired. Mandrill, SendGrid v2, Mailgun's legacy endpoints, and AWS SES v1 have all gone through major deprecation cycles.
The failure may be sudden (API version shut down) or gradual (deprecated endpoints returning intermittent errors before full removal).
Password reset emails, verification links, and order confirmations from your application arrive minutes or even hours after the user requested them. By the time the email arrives, verification tokens have expired, users have given up, and time-sensitive notifications are useless.
Email delays are especially damaging for authentication flows. A password reset email that arrives 30 minutes late means the user can't log in for 30 minutes. A verification email that arrives after the token expires means the user has to start over, if they haven't already abandoned your app.
The delay may be inconsistent, with some emails arriving in seconds and others taking hours, making the problem hard to diagnose and reproduce.
Your Docker Compose setup generated by Claude Code has services that fail to connect to each other. The application container can't reach the database, the backend can't connect to Redis, or the worker can't find the message broker. Everything works when running services individually but fails in Docker Compose.
Docker Compose creates a network where services can reach each other by their service name. When the application code uses 'localhost' or hardcoded IPs instead of service names, or when service names in docker-compose.yml don't match what the application expects, connections fail.
This is especially frustrating because the error messages often just say 'connection refused' or 'host not found' without indicating that the issue is a name mismatch.
The GitHub Actions workflow generated by Claude Code fails on every push or pull request. The workflow YAML may have syntax errors, reference non-existent secrets, use outdated action versions, or fail due to missing permissions. CI/CD is completely broken, preventing automated testing and deployment.
GitHub Actions workflows are notoriously difficult to debug because you can't run them locally (without act), the feedback loop is slow (push, wait, read logs), and error messages often point to symptoms rather than root causes.
The workflow may have worked initially but started failing after GitHub deprecated an action version, a secret expired, or the repository settings changed.
When a modal, drawer, or overlay opens in your application, the background page continues to scroll on mobile devices. Users scrolling within the modal accidentally scroll the page behind it, losing their place. When the modal closes, the page has scrolled to a completely different position.
This is one of the most noticeable mobile UX bugs. It makes modals feel broken, confuses users, and creates a jarring experience. The issue is particularly bad on iOS Safari, which has unique scroll behavior that makes standard CSS solutions insufficient.
Claude Code typically generates modals that work well on desktop (where body overflow: hidden is sufficient) but break on mobile where touch scroll events propagate differently through the DOM.
Your application's layout breaks on very small screens (below 375px width), even though it looks fine on standard mobile sizes. Elements overflow horizontally, text gets cut off, buttons become untappable, and the page requires horizontal scrolling to use.
This affects users with older or smaller phones (iPhone SE, Galaxy A series), users who have increased their system font size, and users viewing your app in split-screen mode on tablets. These are real users who are completely locked out of your app.
Claude Code typically generates responsive CSS targeting common breakpoints (768px, 640px) but doesn't account for screens smaller than 375px, where fixed pixel widths, min-width declarations, and padding cause layout overflow.
Forms in your application are technically functional on mobile but practically unusable. Users report that the page zooms in when tapping input fields, the keyboard covers the submit button, dropdown menus are impossible to select, and multi-step forms lose progress when the keyboard appears.
Poor mobile form usability directly kills conversion rates. Users abandon signups, checkout flows, and contact forms because the experience is too frustrating. This is revenue and engagement you're losing silently.
Claude Code generates forms that work well with a mouse and keyboard but doesn't account for touch interactions, virtual keyboards, and the drastically different viewport behavior on mobile devices.
A small feature was added via npm package but bundle size increased 500KB. The feature doesn't justify the size increase. Build tools show the dependency is being included but it's rarely used, or lighter alternatives exist.
Adding the dependency solved a problem but created a new one: application loads slower for all users.
An endpoint that processes data times out when dataset size increases. The algorithm works correctly for small datasets but degrades exponentially with larger inputs. Response time jumps from 100ms to 10+ seconds as data volume grows.
The algorithm is correct but has poor time complexity that wasn't apparent at scale.
A background job that runs periodically starts consuming more memory with each execution. After hours of running, the application runs out of memory and crashes. The job itself is correct but something isn't being cleaned up properly.
Memory usage climbs steadily despite the job appearing to complete normally.
Application performance degrades significantly after adding a feature that loads related data. Profiling shows massive number of database queries (1 main query + N queries for each result). Adding 50 users slows down response by seconds instead of milliseconds.
The feature works correctly but is fundamentally inefficient, querying the database hundreds or thousands of times for what should be a few queries.
Code with multiple nested async operations becomes deeply nested and hard to follow (callback hell). Fixing bugs or adding features becomes dangerous due to complexity. Code written before async/await was standardized.
Refactoring to async/await would improve readability and maintainability significantly.
Processing large files or datasets causes out-of-memory errors. Profiling shows massive string accumulation. The issue: concatenating strings in a loop creates new string object each iteration.
Simple string concatenation is inefficient when done repeatedly.
Application state becomes inconsistent under certain conditions. Two async operations complete in unexpected order, leaving the application in an invalid state. Clicking buttons rapidly, loading data concurrently, or quickly switching views exposes the race condition.
Works fine in normal usage but fails under concurrent load or rapid user actions.
When multiple users or processes update the same data simultaneously, your application produces incorrect results. Inventory counts go negative, account balances are wrong, duplicate records appear, or the last write silently overwrites earlier changes without merging them.
Race conditions are among the hardest bugs to find because they're non-deterministic. They happen occasionally under load but almost never during manual testing. You might only discover them when a user complains that their changes disappeared, or when financial totals don't add up.
Claude Code generates code that works correctly for sequential operations but doesn't add concurrency controls. Every read-modify-write sequence without locking is a potential race condition waiting to be triggered under production load.
Your application's event-driven architecture works fine in development but collapses under production load. Events pile up in queues, consumers can't keep pace with producers, and end users experience increasing delays in seeing updates, receiving notifications, or having their actions processed.
Event-driven architectures are powerful but introduce complexity that AI-generated code often doesn't handle correctly. The initial implementation works for single-digit users but fails at scale because it lacks consumer scaling, proper partitioning, dead letter queues, and backpressure mechanisms.
Symptoms include growing queue depths, increasing latency on event processing, out-of-memory errors on consumer processes, and eventually dropped events when queues hit their size limits.
Your application's WebSocket connection drops after network interruptions, server restarts, or idle timeouts, and never attempts to reconnect. Users see stale data, missing notifications, and a broken real-time experience until they manually refresh the page.
WebSocket connections are inherently fragile. Mobile networks switch between WiFi and cellular, laptops sleep and wake, load balancers have idle timeouts, and servers restart during deployments. Without automatic reconnection, every one of these common events breaks your app for affected users.
The issue is worst on mobile devices where network conditions change frequently. Users may not realize their connection is dead until they wonder why they haven't received any updates in minutes.
Your API endpoints generated by Claude Code accept any input without validation, allowing malformed data, oversized payloads, or malicious content to reach your business logic and database. There are no checks on field types, lengths, formats, or required fields.
Without input validation, attackers can submit negative prices, inject SQL through string fields, send payloads that crash your server, or store garbage data that breaks your application later. Even non-malicious users can accidentally submit invalid data that causes downstream errors.
This often becomes apparent when your database contains impossible values, when your app crashes on unexpected input, or when a security audit flags every endpoint as vulnerable.
Claude Code generated code with API keys, database passwords, or other secrets hardcoded directly in source files. These credentials are now committed to your Git repository and visible to anyone with access to the code.
This is one of the most common security mistakes in AI-assisted development. The AI often places real credentials inline to make the code immediately functional, without considering that the code will be version-controlled and potentially shared.
You may discover this when GitHub sends a secret scanning alert, when a third-party service notifies you of leaked credentials, or when you notice unexpected charges on your cloud account.
Claude Code generated backend code that constructs shell commands or system calls by concatenating user input directly into the command string. An attacker can inject additional commands by including shell metacharacters like semicolons, pipes, or backticks in their input.
This is especially dangerous in Node.js or Python backends where child_process.exec() or os.system() are used with string interpolation. The generated code may look correct at first glance but opens a direct path to remote code execution on your server.
You might discover this during a code review, a penetration test, or after an attacker has already exploited it to read files, install backdoors, or exfiltrate data from your server.
Files uploaded to or processed by your application come out corrupted. PDFs are unreadable, images show as broken, ZIP archives can't be extracted, and Excel files fail to open. The files appear to be the right size but their contents are garbled.
Binary file corruption typically happens when the application treats binary data as text (applying encoding transformations that destroy the data), when streams are not properly piped, or when files are read and written with mismatched encoding settings.
This issue is particularly insidious because it may only affect certain file types or file sizes, making it hard to reproduce consistently during testing.
Your application creates temporary files for processing (image transforms, PDF generation, CSV exports, file uploads) but never deletes them afterward. Over days or weeks, these orphaned files accumulate and eventually fill the disk, causing the application to crash or become unresponsive.
This is a silent issue that doesn't appear during development or testing because the files accumulate slowly. In production, you first notice it when the server runs out of disk space, uploads start failing, or the database can't write its WAL files.
The root cause is that Claude Code generated the file creation logic but didn't include cleanup logic, error handling that cleans up on failure, or a scheduled cleanup job.
Your application fails when trying to write files to disk, throwing EACCES, EPERM, or permission denied errors. File uploads, log writing, cache storage, or report generation all fail because the application process doesn't have write access to the target directories.
This commonly happens when Claude Code generates code that writes to absolute paths like /tmp, /var, or the project root directory, but the deployment environment (Docker container, cloud function, or restricted server) doesn't allow writes to those locations.
The code works perfectly in local development where you run as an admin user, but breaks immediately in production where the application runs as a restricted service account.
Your integration tests pass when run individually but fail randomly when run as a suite. The failures are non-deterministic: different tests fail on different runs, tests that were passing start failing after adding new tests, and the CI pipeline has become unreliable with intermittent failures.
Flaky tests are a serious productivity drain. Developers lose trust in the test suite, start ignoring failures ('it's just a flaky test'), and eventually stop running tests altogether. Real bugs hide behind the noise of flaky failures.
Claude Code generates integration tests that work in isolation but share database state, use hardcoded ports, rely on test ordering, or have timing dependencies that cause failures when tests run in parallel or in different orders.
Your test suite passes with flying colors but bugs keep reaching production. The tests generated by Claude Code look comprehensive but contain assertions that are too weak, verify the wrong thing, or test implementation details rather than behavior. You have the illusion of safety without the actual protection.
This is more dangerous than having no tests at all because it creates false confidence. Developers merge code because 'all tests pass' without realizing the tests don't actually verify the critical behavior. The test suite becomes expensive to maintain but provides no value.
Common patterns include tests that only check response status codes without verifying response bodies, tests that mock so heavily they're testing the mocks, and tests that assert on object shape but not on computed values.
Your test suite covers utility functions and simple CRUD operations but completely misses the critical business logic: payment processing, access control checks, data transformations, and state machine transitions. The parts of your code that are most likely to cause catastrophic failures if broken have zero test coverage.
Claude Code tends to generate tests for the easiest-to-test code (pure functions, simple helpers) while skipping the complex, stateful, integration-heavy code that actually needs testing the most. The coverage report may show 70% overall but the missing 30% contains all the high-risk logic.
This becomes painfully apparent when a 'small refactor' of the payment flow introduces a bug that charges customers the wrong amount, and no test catches it before production.
A form was scaffolded with basic structure but validation is incomplete. Some fields check for empty values but don't validate format (emails, phone numbers). Others bypass validation entirely due to missing checks. Invalid data is submitted to backend.
Frontend validation is partially implemented but inconsistent across form fields.
User-provided content displayed in template without escaping. Attacker can inject malicious JavaScript that executes in other users' browsers. Form submissions, comments, or user profiles become attack vectors.
Template renders user input directly, trusting it's safe when it's not.
A UI component successfully updates its state but the changes don't appear on screen. The developer confirms the state changed (via console logging) but the component remains visually unchanged. This typically affects forms, lists, and modal dialogs.
The component structure and lifecycle are correct, but something prevents the rendering system from detecting the state change as significant.
A CSS rule was written and is definitely being loaded (visible in dev tools), but it's not applied to elements because a more specific rule is overriding it. This commonly happens after refactoring style organization or adding utility classes.
The style appears in the stylesheet but browsers display the override style instead, confusing developers about what went wrong.
Button or element has an onclick handler or click listener attached but clicking doesn't trigger it. The element responds to other interactions but the click handler isn't called. This often happens after dynamically adding elements or refactoring event binding.
Handler is defined and looks correct but isn't invoked when clicked.
Server-side rendered pages fail to load with template syntax errors. Browser shows 500 error, server logs show the template couldn't be parsed. Changes to template files aren't working as expected.
Template syntax is close to correct but has subtle errors that prevent rendering.
You don't need to be technical. Just describe what's wrong and a verified developer will handle the rest.
Get Help