Troubleshooting
Quick solutions to common issues when building with KwikSaaS.Authentication Issues
OAuth redirect fails or shows error
OAuth redirect fails or shows error
Symptoms: Google/GitHub sign-in redirects to error page, console shows CORS or redirect errors, “Invalid callback URL” message.Solutions:Check Supabase URL Configuration: Go to Supabase Dashboard → Authentication → URL Configuration. Site URL should be
http://localhost:3000 (exact match, no trailing slash). Redirect URLs must include http://localhost:3000/auth/callback.Verify OAuth provider settings: Callback URL in Google/GitHub must match Supabase’s provided URL. Client ID and Secret must be correct. Provider must be enabled in Supabase.Use localhost not 127.0.0.1: Supabase treats these as different origins. Always use http://localhost:3000.Email verification not arriving
Email verification not arriving
Symptoms: Sign up completes but no email received, magic link never arrives, password reset email missing.Solutions:Check spam/junk folder first. Supabase rate limits: Free tier allows 4 emails/hour - wait or upgrade plan. Verify email settings in Authentication → Email Templates. Check Supabase Auth logs in Dashboard → Logs → Auth Logs.
Session not persisting after sign in
Session not persisting after sign in
Symptoms: User signs in but immediately logged out, dashboard shows sign-in page, session lost on page refresh.Solutions:Check
NEXT_PUBLIC_SITE_URL matches the actual URL you’re accessing (include protocol). Verify middleware is running - check middleware.ts matcher patterns. Try incognito mode to rule out cookie issues, or clear site data.Password reset shows Invalid token error
Password reset shows Invalid token error
Symptoms: Reset link shows error page, “Invalid or expired token” message.Solutions:Token expiry: Links expire after 24 hours - request a new one. Check auth callback:
/auth/callback must be in Supabase Redirect URLs. Recovery flow requires type=recovery in URL. The callback sets a recovery cookie - if blocked, reset flow fails.Payment Issues
Checkout returns 400 error
Checkout returns 400 error
Symptoms: Clicking pricing button shows error, console shows “Invalid price” or 400 status.Solutions:Verify price ID in Stripe Dashboard - ensure it starts with
price_ and matches test/live mode. Check plan configuration in src/lib/payments/plans.ts has matching stripePriceIds. Stripe mode mismatch: test keys only work with test products.Webhook signature verification failed
Webhook signature verification failed
Symptoms: Stripe Dashboard shows failed webhooks, console shows “No signatures found matching”, database not updating after payment.Solutions:For local development: Restart
stripe listen command, copy the new whsec_... secret, update STRIPE_WEBHOOK_SECRET in .env.local, restart dev server.For production: Go to Stripe → Developers → Webhooks, verify endpoint URL is correct, use the webhook’s signing secret (not API key).Subscription not appearing in database
Subscription not appearing in database
Symptoms: Payment successful in Stripe, user doesn’t show as subscribed,
user_subscriptions table empty.Solutions:Ensure webhook listener is running: stripe listen --forward-to localhost:3000/api/webhooks/stripe. Check Stripe webhook logs in Developers → Webhooks → Recent events. Verify database migrations with npx supabase db push. Check server logs for errors in webhook handler.Customer portal not opening
Customer portal not opening
Symptoms: “Manage subscription” button doesn’t work, error creating portal session.Solutions:User needs
stripe_customer_id in user_subscriptions table - customer is created on first checkout. Enable portal in Stripe Settings → Billing → Customer portal. User must be authenticated - portal requires active session.Database Issues
Tables missing after migration
Tables missing after migration
Symptoms: “relation does not exist” errors, dashboard shows database errors, can’t insert/read data.Solutions:Run migrations:
npx supabase db push. Or manually execute SQL from supabase/migrations/*.sql in Supabase SQL Editor. Check connection - verify NEXT_PUBLIC_SUPABASE_URL is correct and project is active (not paused).RLS policy blocking access
RLS policy blocking access
Symptoms: Empty data returned from queries, “new row violates row-level security policy”, works in Supabase dashboard but not app.Solutions:Check user authentication - RLS requires authenticated session. Use correct client: client-side uses anon key with RLS, server-side service key bypasses RLS. Review policies in Supabase → Authentication → Policies.
Build and Deploy Issues
Build fails with type errors
Build fails with type errors
Symptoms:
npm run build fails, TypeScript errors in console, deploy fails on Vercel.Solutions:Run type check locally: npm run lint and npx tsc --noEmit. Supabase types may need regeneration with npx supabase gen types typescript. Build may fail if env vars are missing - set all required vars in deployment platform.Environment variables not loading
Environment variables not loading
Symptoms:
undefined values in app, features not working in production, works locally but not deployed.Solutions:Client-side variables must start with NEXT_PUBLIC_. Restart dev server after changes. Server-side variables are available in API routes and server components. For Vercel: add all variables in dashboard and redeploy after adding new variables.Vercel deployment shows old code
Vercel deployment shows old code
Symptoms: Changes not appearing after deploy, Vercel shows successful but outdated.Solutions:Clear Vercel cache by triggering new deployment with “Redeploy” → Clear cache. Check you’re deploying the correct branch. Review build logs for errors.
Development Issues
Hot reload not working
Hot reload not working
Symptoms: Changes require manual refresh, fast refresh errors in console.Solutions:Check for syntax errors - they can break hot reload. Restart dev server with
npm run dev. Clear Next.js cache: rm -rf .next && npm run dev.Tailwind styles not applying
Tailwind styles not applying
Symptoms: Classes have no effect, styles work locally but not in production.Solutions:Check content configuration in
tailwind.config.ts. Use full class names (not computed). Use cn() helper for conditional classes. Clear cache: rm -rf .next && npm run dev.Module not found errors
Module not found errors
Symptoms: Import errors in console, “Cannot find module” messages.Solutions:Reinstall dependencies:
rm -rf node_modules && npm install. Check path aliases - imports should use @/ prefix. Verify tsconfig.json paths. Note that Linux/macOS are case-sensitive.Email Issues
Resend emails not sending
Resend emails not sending
Symptoms: No emails received from app, Resend dashboard shows no activity.Solutions:Check API key -
RESEND_API_KEY must start with re_. Domain must be verified in Resend with DNS records (SPF, DKIM). RESEND_FROM_EMAIL must use verified domain or @resend.dev for testing.Emails landing in spam
Emails landing in spam
Symptoms: Emails sent but go to spam, low deliverability.Solutions:Complete domain verification with all DNS records (SPF, DKIM, DMARC) - wait up to 48 hours for propagation. Avoid spam triggers: no all caps in subject, include unsubscribe link. Use custom domain instead of
@resend.dev in production.