Documentation
Troubleshooting
Common Motoko Base issues and fixes — auth, OAuth, database, email, billing, storage, Sentry, and build failures.
Quick fixes for problems that often appear during first setup or production deploy. For env details see Environment Variables.
Authentication doesn't work
Symptoms: Cannot sign in, session lost on refresh, redirect loops, cookies not set.
| Check | Fix |
|---|---|
BETTER_AUTH_SECRET missing | Set in .env — required in production |
BETTER_AUTH_URL wrong | Must match the URL you open in the browser (including http:// vs https://, port, no trailing slash issues) |
Mismatch with NEXT_PUBLIC_APP_URL | Align both to the same origin in each environment |
| Database down / migrations not run | Verify DATABASE_URL, run pnpm db:migrate |
| Email not verified | Dashboard requires verification — check inbox or use /verify-email |
See Better Auth and Installation.
OAuth callback error
Symptoms: redirect_uri_mismatch, Google/GitHub error after authorize, social buttons disabled.
| Check | Fix |
|---|---|
| Button disabled | Set both GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET (or GitHub pair); restart dev server |
| Callback URL mismatch | Provider console must have exactly {BETTER_AUTH_URL}/api/auth/callback/google or .../github |
| Production vs local | Add separate callback URLs for localhost and production domain |
| Google testing mode | Add your account as a test user on the OAuth consent screen |
See OAuth Setup.
Database connection failed
Symptoms: App crashes on boot, migrations fail, ECONNREFUSED, timeout errors.
| Check | Fix |
|---|---|
DATABASE_URL unset or wrong | Copy from Supabase/host dashboard; never use NEXT_PUBLIC_* |
| Migrations not applied | pnpm db:migrate |
| Pooler vs direct | Runtime: transaction pooler (often port 6543). Migrations: try direct URL (port 5432) if DDL fails |
| Supabase paused project | Restore project in Supabase dashboard |
prepare: false | Already set in src/lib/db/index.ts — required for Supabase pooler; do not enable prepared statements |
See Database and Migrations.
Emails aren't being sent
Symptoms: No verification email after sign-up, forgot-password does nothing, welcome email missing.
| Check | Fix |
|---|---|
| Resend not configured | Set RESEND_API_KEY and EMAIL_FROM |
| Wrong sender | Use verified domain in production; for tests try onboarding@resend.dev |
BETTER_AUTH_URL wrong | Reset/verification links point to wrong host — fix origin |
| Forgot-password page error | Page checks isEmailConfigured() — both Resend vars required |
| Resend dashboard | Check Resend logs for bounces or API errors |
See Email (Resend).
Polar checkout doesn't open
Symptoms: Billing page shows “not configured”, checkout button fails, stays on Free after payment.
| Check | Fix |
|---|---|
| Missing env vars | POLAR_ACCESS_TOKEN, POLAR_PRO_MONTHLY_PRODUCT_ID, POLAR_WEBHOOK_SECRET |
| Sandbox vs production | POLAR_SERVER=sandbox with sandbox token/product — or production with live credentials |
| Webhook URL | {APP_URL}/api/billing/webhooks/polar — must be reachable from Polar |
| After checkout | Billing page uses getFreshBillingSummary on success redirect; confirm webhook delivered |
| No Polar customer | User needs a Polar customer (created on sign-up when billing configured) before portal |
See Payments (Polar).
R2 upload fails
Symptoms: Storage page shows config message, presigned URL error, browser upload CORS failure, 403 on PUT.
| Check | Fix |
|---|---|
Missing R2_* vars | Set account ID, access key, secret, bucket name |
| Bucket name with slash | my-bucket/demo → bucket my-bucket, prefix demo/ — or use R2_PREFIX |
| CORS | Add your app origin to R2 bucket CORS policy in Cloudflare |
| File too large / wrong MIME | Limits in src/features/storage/config.ts |
| HEAD validation fails | Server validates upload after PUT — check object exists in R2 dashboard |
See Storage (R2).
Sentry isn't receiving errors
Symptoms: No issues in Sentry dashboard after throwing a test error.
| Check | Fix |
|---|---|
Testing in next dev | Sentry is disabled during dev — use pnpm build && pnpm start or test on deployed production |
| DSN unset | Set NEXT_PUBLIC_SENTRY_DSN |
| Wrong project | Confirm DSN matches the Sentry project you are viewing |
| Ad blockers | Browser may block Sentry — try /sentry-tunnel route or test server-side error |
| Source maps | Set SENTRY_AUTH_TOKEN, SENTRY_ORG, SENTRY_PROJECT at build time for readable stacks |
See Monitoring (Sentry).
Build fails
Symptoms: pnpm build exits with errors locally or in CI.
| Check | Fix |
|---|---|
| Node version | Requires Node ≥ 22 — run node -v |
| Type errors | pnpm typecheck — fix reported TypeScript issues |
| Lint errors | pnpm lint |
| Missing env at build | Most vars are runtime-only; Sentry upload vars needed only if using source maps |
| MDX / docs | Run pnpm install so postinstall (fumadocs-mdx) completes |
| Lockfile | Use pnpm install — do not mix npm/yarn |
pnpm lint && pnpm typecheck && pnpm test && pnpm buildStill stuck?
- Re-read Installation and Production Setup
- Compare your
.envagainst.env.example - Check integration dashboards (Resend, Polar, Cloudflare, PostHog, Sentry)
- Search the repo README,
docs/style-guide/(maintainer-facing coding conventions), and feature READMEs undersrc/lib/email/,src/lib/security/, etc.
Scripts — Command reference.
Configuration Reference — Config file index.
Maintainer style guide — Internal coding conventions for agents and contributors live in docs/style-guide/ at the repository root (not part of the public docs site).