Step-by-step guides for the most common Lovable problems, written by real developers.
Edge functions work in production but hard to test locally. Need to deploy to test. No local execution environment. Debugging is difficult without local testing.
Supabase CLI provides local development environment for testing functions before pushing to production.
Stripe webhook endpoint receives events but signature verification fails. Webhook handler rejects legitimate events. Payment events aren't processed correctly. Security validation throws errors.
Stripe signs webhooks with your endpoint secret. Verification ensures events are authentic and haven't been tampered with. Signature mismatch indicates wrong secret or data corruption.
Calling third-party APIs from React app fails with CORS error. 'Access-Control-Allow-Origin' header missing. Works in backend but not client-side. Browser blocks cross-origin request.
CORS restrictions prevent client-side code from calling arbitrary APIs unless the API explicitly allows it. Solution requires using backend proxy or Edge Functions.
Webhook endpoint configured in Supabase but never receives events. Database changes occur but webhook isn't triggered. Endpoint appears to work when tested but events don't arrive.
Webhooks require proper table configuration, filter setup, and endpoint accessibility. Events must be published and delivered correctly.
Edge function requests timeout after 120 seconds with 504 Gateway Timeout. Function doesn't execute or returns 500 error. Async operations timeout. Functions work locally but fail in production.
Supabase Edge Functions have strict timeout limits and require optimization for fast execution. Network calls and database queries must complete quickly.
Test payments work but production payments fail. Using test keys in production or live keys in development. Webhooks not firing in right environment. Keys mixed up causing transaction failures.
Stripe has separate test and live environments with different keys. Mixing keys between environments breaks payment flow.
Need to perform operations that bypass RLS for server-side actions. Can't use regular client for certain admin operations. RLS blocking necessary backend logic.
Supabase admin client uses service role key which bypasses RLS. Use only in secure backend environment, never expose service role key to client.
After authenticating with Supabase, the user session disappears when the page is refreshed. Users are logged out unexpectedly, and the authentication state is not being maintained across browser sessions.
This typically happens because the auth session data is stored in memory only, rather than being persisted to localStorage or sessionStorage. When the page reloads, the in-memory state is lost.
Database queries fail with 'new row violates row-level security policy' or 'permission denied' errors. Users cannot read or write to tables despite having authentication credentials.
This occurs when RLS policies are too restrictive or missing entirely. RLS must be explicitly enabled per table and policies must allow the current auth context.
OAuth authentication fails with error 'redirect_uri_mismatch' or callback page shows blank/error. Users cannot sign in via GitHub or Google because the configured redirect URL doesn't match.
OAuth providers validate that the redirect URL matches exactly what was registered. Any difference in protocol, domain, path, or query parameters will cause the mismatch error.
Users experience sudden logout after being idle or when making requests. API calls start failing with 401 Unauthorized. The JWT token has expired but the app didn't refresh it before it became invalid.
By default, Supabase tokens expire after 1 hour. Without proper refresh token handling, expired tokens cause failures silently rather than triggering re-authentication flow.
Supabase anon key is visible in browser. Someone could copy it and use it to call Supabase API directly. Key is committed to Git. Security concern: data exposed via anon key.
Anon keys must be exposed on client but should never have direct table access. RLS policies protect data from unauthorized access even with key.
User logs in successfully but gets redirected to login page again. Auth state is lost after clicking a link or navigating. Session appears to end prematurely during redirect flow.
Auth state must persist during navigation. If state isn't properly restored from storage before redirect, users see login page again.
Querying JSON columns returns no results or errors. Filter on nested JSON properties doesn't work. JSONB operators don't execute correctly.
PostgreSQL JSONB requires specific operators and syntax. Regular comparison doesn't work on JSON fields.
Users can read data from table but cannot insert or update. 'permission denied' error on insert/update despite having select access. RLS policies inconsistently applied across operations.
Each database operation (SELECT, INSERT, UPDATE, DELETE) needs its own RLS policy. Common mistake is creating only SELECT policy and assuming others inherit.
When users submit forms or interact with the app, data appears to save locally but never reaches the database. Supabase inserts and updates silently fail without throwing errors. Data is lost on page reload.
This typically happens when insert/update operations fail due to RLS policies, missing required fields, type mismatches, or unhandled promise rejections.
Realtime subscriptions are set up but changes made by other users or external updates are not reflected in the UI. The app shows stale data even though data changed in the database.
Realtime requires explicit table replication configuration. Many tables have realtime disabled by default. Subscriptions also need to be set up before the page loads.
App performance degrades as data grows. Loading 100 items runs 101 queries (1 for items + 1 per item for related data). Database becomes bottleneck with high latency and connection pool exhaustion.
N+1 occurs when fetching parent records, then looping to fetch each child separately, instead of joining in single query.
Attempting to delete or update records fails with 'foreign key constraint violation'. Child records reference the record being deleted, preventing the operation. This breaks the intended delete flow.
Foreign keys enforce referential integrity. When records are related, the database prevents orphaned references unless cascade rules are configured.
Requests start failing with 'too many connections' or connection timeout errors. Error appears after app runs for a while or under load. Connection pool is exhausted.
Database has limited connections. Without proper connection management, connections leak and pool becomes exhausted.
Deployment fails because database migrations encounter errors. Schema changes conflict with existing data or migrations are applied in wrong order. Database becomes in inconsistent state, blocking the deployment.
Migrations must be designed carefully to handle existing data without data loss. Supabase maintains migration history and applies them sequentially.
API keys and configuration values are undefined in production. Supabase URL and API key return undefined, causing all API calls to fail. Works locally with .env.local but not in production.
Vite only exposes variables prefixed with VITE_ to the client. Production requires proper build-time or runtime environment setup.
API requests to Supabase fail with CORS error in production. 'Access-Control-Allow-Origin' header missing or not matching domain. Works locally but fails on deployed site.
CORS policy requires server to explicitly allow requests from client domain. Browser blocks cross-origin requests without proper headers.
Styled-components, Emotion, or other CSS-in-JS works in dev but fails in production build. Styles disappear or don't apply. Class names don't match between server and client.
CSS-in-JS requires proper build configuration for server-side rendering and style extraction.
Users don't see app updates. Old JavaScript cached in browser. New features don't appear even after deployment. Cache headers prevent fresh content.
Browser caches static assets for performance. Without proper cache headers, users see stale code.
Features requiring HTTPS (geolocation, service workers, secure cookies) don't work on localhost:5173. Browser blocks insecure context APIs. Need to test HTTPS-only features in development.
Development typically uses HTTP, but some APIs require HTTPS. Self-signed certificates enable local HTTPS testing.
Import aliases work in development (@/components) but fail in production build. Build fails with 'cannot find module' errors. Aliases not recognized by TypeScript or bundler.
Vite aliases require configuration in both vite.config.js and tsconfig.json. Missing either causes resolution failures.
App works perfectly in development (npm run dev) but production build shows blank page (npm run build). No errors in console. Static assets fail to load with 404. JavaScript doesn't execute.
Production builds use optimized bundling that can expose issues hidden in dev mode. Base path, asset references, and build configuration mismatches cause blank pages.
Vite dev server starts but HMR connection fails with 'WebSocket connection failed' or 'net::ERR_CONNECTION_REFUSED'. Changes require manual page refresh instead of hot reload. Development experience is slow.
HMR requires WebSocket connection from browser to dev server. Network configuration or firewall can block the connection.
File upload to Supabase Storage fails with CORS error. 'Access-Control-Allow-Origin' missing in response. Works with API key but not with RLS. Uploads blocked from production domain.
Supabase Storage requires CORS configuration and proper bucket settings for client-side uploads.
Emails sent by your Lovable app (welcome emails, password resets, notifications, receipts) are landing in users' spam or junk folders instead of their inbox. Some users never receive the emails at all.
Poor email deliverability means users miss critical communications — they can't reset passwords, don't receive order confirmations, and miss important notifications. This directly impacts user trust and business operations.
The problem may be inconsistent: emails reach Gmail but not Outlook, or they work for some users but not others. Corporate email addresses often have stricter spam filters that block your emails entirely.
Your Lovable app's email verification flow is broken. Users sign up but can't verify their email because the verification link doesn't work, leads to an error page, has already expired, or the verification email never arrives.
Email verification is essential for preventing fake accounts and ensuring users own their email address. When it's broken, legitimate users are locked out of your app after signing up, creating a terrible first impression.
The issue might be specific to certain email providers, or it might affect all users. Some users receive the email but the link fails; others never receive the email at all.
Emails sent from your Lovable app contain blank spaces or literal placeholder text where dynamic content should be — for example, 'Hello {{name}}' instead of 'Hello John', or 'Your order #{{orderId}}' with blank values.
This makes your app look unprofessional and can confuse users. They receive emails that don't contain the information they need, like order details, account information, or personalized content.
The issue might affect all emails or only certain templates, and might work correctly in development but fail in production.
Google Analytics (GA4) shows zero or very low traffic for your Lovable app, even though you know users are visiting. Page views aren't being recorded, events aren't firing, or the Real-Time report shows no active users when you're actively browsing the site.
Without analytics, you're flying blind — you can't see how many users visit your app, which pages they use, where they drop off, or whether your marketing efforts are working. Accurate analytics are essential for making data-driven decisions about your app.
The problem may be total (no data at all) or partial (some pages tracked, others not; page views work but events don't).
Stripe checkout works perfectly in test mode but fails when you switch to live/production keys. The checkout button does nothing, the Stripe form shows errors, or payments process but your app doesn't receive the confirmation.
Payment processing failures directly impact your revenue. Every failed checkout is a lost customer who may never return. This is the most business-critical bug your app can have.
Common symptoms include: the checkout redirect failing silently, the payment succeeding on Stripe's dashboard but the webhook not updating your app, or the live API key being rejected.
Google Maps displays a gray box, 'For development purposes only' watermark, an error message, or doesn't load at all in your Lovable app. The map area may appear blank, show a broken image, or display a 'This page can't load Google Maps correctly' error.
Maps are essential for location-based apps, store finders, delivery tracking, and property listings. A broken map makes these features completely unusable.
The issue typically appears as one of: a completely empty div where the map should be, a map with a dark overlay and watermark, or a JavaScript console error about the Maps API.
When you or your users share your Lovable app's links on social media (Facebook, Twitter/X, LinkedIn, iMessage), the preview shows incorrect information — wrong title, missing description, no image, or a generic fallback instead of your page-specific content.
Social sharing previews are crucial for marketing and user acquisition. A professional-looking preview with the right image and description dramatically increases click-through rates. A broken or generic preview makes your link look like spam.
The issue may differ by platform — Twitter might show a preview but Facebook doesn't, or the image appears on LinkedIn but the description is wrong on WhatsApp.
Your Lovable app looks fine on desktop but the layout is broken on mobile devices — content overflows the screen, text is too small to read, buttons are impossible to tap, or elements overlap each other.
Mobile users often make up 60-80% of web traffic. If your app doesn't work on phones, you're losing the majority of potential users. Common symptoms include horizontal scrolling, elements hidden off-screen, and navigation that's unusable on small screens.
The issues may vary between different phones and screen sizes, making it hard to identify a single root cause.
When users tap on an input field in your Lovable app on mobile, the on-screen keyboard pushes content off the screen, hides the input field behind the keyboard, or causes the entire layout to shift and break.
This is extremely frustrating for users trying to fill out forms, write messages, or search. They can't see what they're typing, buttons become unreachable, and the app feels completely broken during text input.
The problem is particularly bad on iOS where the keyboard behavior differs significantly from Android, and fixed-position elements (headers, footers, CTAs) cause additional complications.
Touch interactions in your Lovable app don't work on mobile devices. Swipeable carousels don't respond to swipes, drag-and-drop features are unusable, or pull-to-refresh doesn't trigger. Elements that should respond to touch gestures simply don't react.
Touch interactions are fundamental to mobile user experience. Features like image carousels, sortable lists, and swipe-to-delete that work perfectly with a mouse often fail completely on touchscreens.
The issues stem from the fact that mouse events (click, mousedown, mousemove) and touch events (touchstart, touchmove, touchend) are different, and AI-generated code often only implements mouse events.
App memory usage grows over time. Performance degrades after extended use. DevTools memory profiler shows detached DOM nodes and event listeners. Browser tab becomes unresponsive.
Event listeners and subscriptions must be cleaned up when components unmount. Not removing them causes memory to accumulate.
React components render on every state change even when their props don't change. Performance degrades with large lists. User interactions lag. DevTools Profiler shows excessive renders.
React re-renders components when props or state change. Unnecessary renders occur when parent state updates but child doesn't need the new data.
App takes 5+ seconds to load initial page. Blank white screen for extended period. Users see slow Time to First Contentful Paint (FCP) and Time to Interactive (TTI). Performance metrics are poor.
Page load speed depends on bundle size, network latency, and resource blocking. Optimizations include code splitting, lazy loading, and resource prioritization.
Coming from Next.js Image component, Vite React app loads unoptimized images. No automatic responsive images or lazy loading. Performance metrics show large image bytes.
Vite doesn't provide built-in image optimization like Next.js. Manual optimization or third-party tools needed.
First call to Edge function is slow (2-5 seconds). Subsequent calls are fast. Cold start is noticeable for users. Function invocation time is unpredictable.
Serverless functions have cold start delay when first deployed or after inactivity. Function container spins up and loads dependencies.
Images are loading large uncompressed files (5MB+). Page load is slow because image downloads are slow. High resolution images used even on mobile. No lazy loading.
Web images need optimization for format, size, and lazy loading. Unoptimized images account for >50% of page weight in many sites.
App performance noticeably slower with console.log in render. Removing logs makes app faster. Lots of logging output in DevTools console. Re-renders feel sluggish.
Console.log in render code executes on every render. Heavy logging causes measurable performance hit, especially during scrolling or animations.
When you make changes in Lovable's editor, the live preview doesn't update. You modify text, add components, or change styles, but the preview still shows the old version. You have to manually refresh or sometimes even restart the preview to see changes.
The live preview is one of Lovable's key features — seeing your changes instantly is essential for an iterative design workflow. When it breaks, development becomes painfully slow as you're constantly refreshing and waiting.
The issue might be intermittent (works sometimes, not others), specific to certain file types, or happen consistently after making certain kinds of changes.
Data changes in your Lovable app don't appear in real-time for other users. When one user creates, updates, or deletes a record, other users (or even the same user in another tab) don't see the change until they manually refresh the page.
Real-time functionality is essential for chat apps, collaborative tools, dashboards, and notification systems. When it breaks, your app feels sluggish and outdated compared to modern web applications.
The issue may be subtle — some tables update in real-time while others don't, or real-time works for inserts but not updates or deletes.
Your Lovable app uses WebSocket connections for real-time features (chat, notifications, live updates), but the connections keep dropping. Users see messages arrive late, live data stops updating, or the app shows 'disconnected' states frequently.
WebSocket connections are long-lived and sensitive to network changes. Mobile users switching between WiFi and cellular, users on unstable connections, and server-side timeouts all cause disconnections that need to be handled gracefully.
Without proper reconnection logic, a single disconnection means the user's real-time features stop working until they refresh the entire page.
Your Lovable app's file upload feature accepts any file type without validation, potentially allowing users to upload malicious scripts, executable files, or oversized files that could compromise your server or other users.
Without proper file validation, an attacker could upload a PHP script, an HTML file containing JavaScript, or a file disguised as an image that actually contains malware. If these files are served back to users, the malicious code could execute.
This is especially dangerous if uploaded files are stored in a publicly accessible location and served directly to users without content-type validation.
Your Lovable app has API keys, database credentials, or other secrets visible in the browser's source code or network requests. Anyone who views your site can see these keys and potentially abuse them.
This is one of the most critical security issues in AI-generated apps. Lovable may place API keys directly in your frontend JavaScript, making them accessible to anyone who opens browser developer tools. Attackers can use these keys to access your database, send emails on your behalf, or rack up charges on your payment processor.
You might discover this when you receive an unexpectedly high bill from a service, when your database is tampered with, or when a security-conscious user reports the exposure.
Your Lovable app displays user-submitted content (comments, profile names, form inputs) without properly sanitizing it. This allows attackers to inject malicious JavaScript that runs in other users' browsers.
Cross-site scripting (XSS) is a serious vulnerability that can steal user sessions, redirect users to phishing sites, or modify what your app displays. If your app has any feature where one user's input is shown to another user, it may be vulnerable.
The issue often goes unnoticed until someone submits a script tag in a form field and it executes, or until your app is flagged in a security scan.
Your Lovable app either blocks legitimate requests with CORS errors or is configured with overly permissive CORS settings (Access-Control-Allow-Origin: *) that allow any website to make requests to your API.
CORS errors appear as failed API calls in the browser console, preventing your app from communicating with its backend or third-party services. On the other hand, wildcard CORS settings mean any malicious website could make requests to your API on behalf of your users.
This commonly happens when your frontend and backend are on different domains, or when Lovable generates API routes without proper CORS configuration.
Your Lovable app's file storage is full and users can no longer upload files, images, or documents. New uploads fail with quota or storage limit errors.
As your app grows and users upload more content, you'll eventually hit the storage limits of your Supabase plan. This can happen suddenly when a feature goes viral or gradually as content accumulates over time.
The problem affects all file operations — not just new uploads but potentially also file transformations, thumbnails, and temporary files that consume storage silently.
Users trying to download large files (PDFs, exports, media) from your Lovable app experience timeouts, incomplete downloads, or connection resets. The download starts but never completes, or fails with a network error.
This commonly happens with generated reports, data exports, or media files that exceed a few megabytes. The download may work fine for small files but consistently fail for anything larger.
The problem is worse on mobile connections and may appear as a spinning indicator that never completes or a partially downloaded corrupt file.
When users try to upload images in your Lovable app, the upload either fails entirely, succeeds but the image appears broken or corrupted, or the image uploads but never displays correctly on the page.
Image uploads are a core feature for many apps — profile pictures, product images, gallery uploads. When they break, users can't complete essential tasks and the app feels unreliable.
The issue may appear in different ways: a spinner that never completes, an error message after selecting a file, a broken image icon where the photo should appear, or images that upload fine on desktop but fail on mobile.
Browser becomes unresponsive. useEffect runs infinitely, making thousands of API calls. Network tab shows repeated requests. Browser memory increases until crash.
Infinite loops occur when dependency array is missing or incorrect, causing effect to run on every render, which updates state, causing re-render, repeating infinitely.
Console warning: 'Each child in a list should have a unique key prop'. List re-renders cause wrong components to update. List items in wrong order after dynamic changes.
React uses keys to identify list items. Without unique keys, React reuses component instances incorrectly.
Single component error crashes entire app. White screen or error overlay shown to users. No graceful error handling. Error in child component propagates up.
React Error Boundaries catch errors in component trees. Prevents entire app from crashing due to single component error.
Dark mode toggle doesn't work or resets on page reload. Classes like 'dark:bg-gray-900' don't apply when dark mode is enabled. Theme preference not saved.
Dark mode requires class management on root element and localStorage persistence. Tailwind dark mode has multiple strategy options.
Tailwind classes are written correctly but styles don't apply to elements. Custom CSS conflicts with Tailwind. Class purging removes needed styles or adds unwanted ones.
Tailwind requires proper configuration of content paths for class scanning. Conflicts occur when CSS specificity issues override Tailwind utilities.
App looks perfect on desktop but mobile screens show broken layout - text overlaps, buttons are cut off, content is unreadable. Horizontal scrolling required. Tailwind classes not applying correctly at smaller breakpoints.
Mobile responsiveness requires testing at actual mobile sizes and using Tailwind breakpoint prefixes (sm, md, lg) to adapt layout.
Strict mode enabled but type errors prevent build. 'Cannot assign type' and 'missing type' errors. Null/undefined safety enforced. Code works but TypeScript won't compile.
Strict mode enforces stricter type checking. Requires more explicit typing but catches bugs early.
Clicking submit button multiple times creates duplicate records. Data submitted in wrong order due to async operations completing out of sequence. UI doesn't disable button during submission, causing race conditions.
Async form submissions need proper loading state to prevent duplicate submissions. Promises can resolve in any order, creating data inconsistencies.
useContext() hook returns undefined even though context is defined. 'Cannot read property of undefined' errors when accessing context value. Context hook used outside provider scope.
Context consumers must be wrapped in their provider component. Using context outside provider scope or with missing provider returns undefined.
Changes to tailwind.config.js don't appear in development. Need to restart dev server to see theme changes. New colors, spacing, or custom utilities don't apply.
Vite should watch tailwind.config.js but sometimes changes aren't detected. Manual server restart required.
Warning: 'Each child in a list should have a unique key prop' when using fragments. Can't add key to <> syntax. Lists don't render correctly with fragment groups.
Fragments in lists need keys when rendering multiple elements per item. Shorthand <> syntax doesn't support keys.
Form inputs don't update as user types. Values appear frozen. Submitted data shows old/stale values. Controlled inputs and state are out of sync.
React forms require proper state binding with onChange handlers and defaultValue or value props to keep inputs and state synchronized.
ESLint shows 'missing dependency in useEffect' or 'exhaustive-deps' warning. Code works but warning suggests adding dependencies. Adding dependencies causes infinite loops. Stale closures reference old values.
React hooks require explicit dependency arrays to track when effects should re-run. Missing dependencies cause stale closures; extra ones cause infinite loops.
Styles can't be overridden despite being written after conflicting rules. !important needed everywhere. Third-party styles override custom styles. CSS cascade not working as expected.
CSS specificity determines which rule applies when conflicts occur. Higher specificity always wins. Understanding selector specificity is essential.
Modal dialog stays open after clicking close button or outside. Multiple modals stack without closing previous ones. Backdrop remains visible even when modal closes. Z-index issues cause modals to appear behind other content.
Modal state must be properly managed with React state and backdrop click handlers. CSS z-index requires careful layering.
Zustand state changes in store but components don't re-render. Updates work in other components but not in specific one. Selector hook returns stale data.
Zustand uses selector pattern to optimize re-renders. Improper selectors or store structure can cause missed updates.
You don't need to be technical. Just describe what's wrong and a verified developer will handle the rest.
Get Help