Skip to main content

Blog · Spoke

lovable app hangs after login? Fix the freeze

Lovable app hangs after login? Check the Supabase auth callback, stale session, and redirect settings to get users through sign-in again today.

By Dima K. Published

Lovable App Hangs After Login: Fix the Supabase Freeze

The login worked. That is the part that makes this bug so confusing. The password was right, Supabase accepted it, a session was handed back, and the spinner is still turning. The freeze is not the login failing. The freeze is the login succeeding and your app refusing to do anything with the success.

Once you see it that way, the fix gets a lot smaller. Most operators chase the wrong half of this. They check redirect URLs, they reset passwords, they ask the AI to “fix the login,” all on the assumption that authentication broke. It didn’t. The moment Supabase says “this person is who they claim to be” and hands control back to your code, your code goes and does something it shouldn’t, and that something is the wall everyone gets stuck behind. If you are sitting with Lovable open in one tab and Supabase in another, this is the right place to start.

What is actually happening under the hood

Here is the mechanism in plain words. Supabase gives you a way to react to login: a listener called onAuthStateChange() that fires the instant a user’s auth state flips. The intended use is tiny. The user logged in, so flip a piece of local state to “signed in,” and let the rest of the app react to that flag on its own time.

What Lovable’s generated code often does instead is treat that listener as the place to do the heavy lifting. It marks the callback async, then inside it reaches into the database to fetch a profile, or kicks off a redirect, or creates a row, all before the login flow has finished settling. This is a close cousin of the failure in lovable supabase connection lost: the database is technically reachable, but the path your app takes to it stalls at exactly the wrong moment.

“Lovable generates an asynchronous callback inside Supabase’s onAuthStateChange() listener that makes database calls during the authentication flow.”

Tomás Pozo, 2025

That is the deadlock. Auth fires the listener. The listener, mid-handoff, calls back into auth-adjacent work that needs the handoff to already be done. So it waits. And the handoff waits on the listener. Two things politely waiting on each other forever, while the user watches a spinner that will never stop. The login worked perfectly. The code you wired to celebrate it is what hangs.

“onAuthStateChange does not trigger intermittently, and refreshSession/getUser hangs indefinitely.”

Supabase GitHub Issues, 2025

Walking through the fix

Once you understand it is a circular wait, the repair is mechanical. Five steps, in order of how often they are the real cause.

First, gut the auth listener. Open the file where Lovable wires up Supabase auth and find supabase.auth.onAuthStateChange(...). If that callback is marked async, or if it calls await, getUser(), from('profiles'), or a profile insert, that is your deadlock. Strip the callback back to the bare minimum: let it set local state and nothing else. Move every profile read into a separate useEffect that runs after a confirmed session already exists. Resist the urge to paste the symptom into Lovable’s chat and ask it to “fix the login,” because the generated patch tends to shuffle code around without removing the actual wait, the same compounding trap covered in bolt.new doom loop. This is the case that eats the most hours while everything around it looks completely normal, which is exactly why it goes last on most people’s list and should go first on yours.

Second, check whether the first signed-in query is being denied. A different signature: the spinner hangs only for real users, while your own test account occasionally slips through. That asymmetry points at row-level security. Open the Supabase policies for profiles, or whichever table the app reads the moment after login, and confirm authenticated users can select their own row. If you auto-create rows on signup, confirm the insert policy matches the same auth.uid() logic. The session is valid. The query it triggers is the thing getting bounced.

Third, clear a stale session out of local storage. If the bug only shows up in one browser, or only after you changed auth settings earlier in the day, you have old session data poisoning the well. In Chrome, open DevTools, Application, Local Storage, and remove the old Supabase auth keys for the site. Sign out fully and test again. If it works in incognito but not your normal tab, this is almost certainly it: stale data convinces the app it should already be signed in while Supabase quietly repairs the session in the background, and the two disagree.

Fourth, check the redirect URL against the live domain. When login works in Lovable preview or on localhost but freezes on the real production domain, the redirect allowlist is the suspect. Compare the exact site URL in Lovable with the allowed redirect URLs in Supabase Auth: protocol, subdomain, trailing slash, and whether both preview and production hosts are listed. Supabase sends the user back expecting one domain while the app is running on another. The token arrives fine. The route handoff never finishes.

Fifth, gate the first render until the session is ready. Some users get through on a refresh while others get stuck only on the very first login after signup. That timing tell means your code is asking “are we logged in?” before Supabase has finished answering. Find any code that calls getSession() or checks user on the first render and immediately redirects when it gets back null. Add a short loading gate that waits for Supabase to finish restoring the initial session. The page is asking the question a half-second too early, and that half-second is enough to bounce people into a loop or a blank screen.

Why the app never tells you this is happening

Notice what every one of these has in common. None of them is a crash. The server is up. The homepage is fine. Supabase is healthy. The login itself succeeds. So nothing in the stack has any reason to raise its hand, because from each individual piece’s point of view, nothing went wrong. The breakage lives in the seam between the pieces, in the handoff, and seams are exactly what no single tool watches.

That is why you find out from a user, not from your tools. The honest alert would read “login succeeded but the app stalled before loading the account page for 7 users.” What you actually get is silence, then a support message. It is the same blind spot that makes a finished-but-broken app look healthy in my ai-built app crashed: every piece reports fine while the thing your users actually need has stopped working. NoCrash watches the seam: it walks the real sign-in path from the outside, the same boundary your paying users cross, and tells you in plain language the moment they stop getting through. Connect your app free at nocrash.io and the stalled spinner becomes a message to you instead of a complaint from them.

So move the database calls out of that listener tonight, while the bug is fresh and you remember exactly where it lives. The goal was never a better console to keep refreshing. It was not having to refresh at all.

— NoCrash

Common questions

Frequently asked

Why does my Lovable app hang only after login, not before?
Because the public parts can load fine while the signed-in path breaks during the auth handoff. Check what runs right after Supabase returns a session.
What's the onAuthStateChange deadlock in plain English?
It means your app is reacting to "user logged in" by running extra async code before the login flow is finished. Move database work out of the listener and retest.
Will Lovable's AI fix this if I ask?
Sometimes, but this is the kind of bug where the generated patch can move code around without removing the real wait. Ask for one narrow change: keep the auth listener synchronous and move profile fetches later.
How do I tell if it's a Supabase issue or a Lovable issue?
If Supabase auth works in isolation but the Lovable UI freezes after the session returns, the handoff code is the likely problem. Test the login in an incognito window, then inspect the first signed-in query.
How do I prevent this from happening next time?
You need something that watches the app from the outside and tells you when real users can no longer get through the login path. NoCrash fits that category: it catches the broken sign-in flow before the next customer email becomes your alert.

Stop finding out from your customers.

One morning message telling you what ran clean and what didn’t. Free forever on 3 things to watch.