Troubleshooting

Specific problems and how to fix them. Each entry lists the symptom, the likely cause, and the fix. If your problem isn't here, check the FAQ or email support@arkteams.io.

Deployment issues

Vercel build fails with "Module not found"

Symptom. The Vercel deployment fails early in the build with something like Error: Cannot find module 'xyz'.

Cause. Missing dependency in package.json, or npm install wasn't run before pushing, or a node_modules reference that shouldn't be tracked.

Fix.

  1. Locally: rm -rf node_modules package-lock.json && npm install.
  2. Confirm the missing module is in package.json under either dependencies or devDependencies.
  3. Commit the updated package-lock.json and push.
  4. If you accidentally committed node_modules: add it to .gitignore, then git rm -r --cached node_modules, commit, push.

Vercel build fails with "Environment variable not defined"

Symptom. Build fails with a message like Error: NEXT_PUBLIC_SUPABASE_URL is not defined.

Cause. You haven't set the environment variables in Vercel's project settings, or you set them only for Development and not Production.

Fix.

  1. Vercel dashboard → your project → SettingsEnvironment Variables.
  2. Confirm every variable from .env.example is present.
  3. For each, confirm it's checked for all three environments (Production, Preview, Development).
  4. Trigger a new deployment: Deployments → latest → Redeploy.

Vercel deployment succeeds but the site shows a blank page

Symptom. Build completes, but visiting the URL shows a blank page with a client-side error in the browser console.

Cause. Usually one of: environment variable typo, wrong Supabase URL, or an unhandled error in the app root.

Fix.

  1. Open the browser console on the blank page. Read the error.
  2. If it's a Supabase connection error: re-copy the URL and anon key from Supabase → SettingsAPI into Vercel's env vars. Redeploy.
  3. If it's a component error, note the stack trace and paste it into Claude Code or support.

The site loads but API calls return 401 / 403

Symptom. The page renders, but data doesn't. Browser console shows 401 or 403 responses from Supabase.

Cause. The anon key doesn't match the URL, or RLS policies are blocking legitimate reads.

Fix.

  • 401 (unauthorized): your anon key is wrong. Re-copy from Supabase.
  • 403 (forbidden): RLS is blocking the query. Open Supabase → AuthenticationUsers — confirm your user exists. Open DatabasePolicies — confirm the policy for the relevant table allows the operation. If you haven't customized policies, reapply the schema.

Database issues

"Running the schema" fails with "relation already exists"

Symptom. Pasting schema.sql into Supabase's SQL editor fails with ERROR: relation "<table>" already exists.

Cause. You've already run the schema once (or partially), so creating the table again conflicts.

Fix. Three options, pick one:

  • Start fresh (recommended for a new project): go to Supabase → SettingsGeneralReset Database. Then paste schema.sql again.
  • Drop conflicting tables manually: in the SQL editor: drop table if exists <table> cascade; — only do this if the table has no data you care about.
  • Skip existing tables: open schema.sql, delete the create table blocks for tables that already exist, and run only the new ones. Tedious but safe.

I can sign up but can't log in

Symptom. The sign-up form completes successfully. You click the confirmation email link. Then the login page rejects your password.

Cause. Supabase's Site URL setting doesn't match your deployment domain, so the session cookie doesn't bind correctly.

Fix. Supabase → AuthenticationURL ConfigurationSite URL → set to your production URL (e.g., https://my-crm.vercel.app). Save. Sign out, sign in again.

Confirmation emails point to localhost

Symptom. The sign-up confirmation email link starts with http://localhost:3000/... instead of your production URL.

Cause. Same as above — Site URL hasn't been set.

Fix. Same as above, then request a new confirmation email.

"Permission denied for table X" from a deployed product

Symptom. A database query fails with permission denied for table X from inside the product.

Cause. Either RLS is enabled but there's no policy for the current user's role, or you're trying to write to a table with a select-only policy for your role.

Fix.

  1. Open the table in Supabase → AuthenticationPolicies.
  2. Confirm there's at least one policy matching the current user's role (check via auth.uid() and the team_members membership).
  3. If the policy is there but still denying: run the failing query in the SQL editor with explain to see what's filtering.

Migration failed halfway through

Symptom. You ran a migration SQL file and it failed partway — some tables were altered, others weren't.

Cause. Supabase's SQL editor doesn't wrap multi-statement migrations in a transaction by default. If a create table succeeds and the next create policy fails, the first statement is already committed.

Fix.

  1. Wrap future migrations in begin; ... commit; so they're atomic.
  2. For this migration: run the remaining statements individually after fixing the error.
  3. If the migration is unrecoverable, restore from the backup you took before running it (you did take one, right?).

Authentication issues

The first user isn't becoming the admin

Symptom. You signed up as the first user, but you don't see admin menu items. A test user who signed up second has them.

Cause. The admin-promotion trigger fires on the first row in the profiles table, and Supabase creates profiles rows via a trigger on auth.users. If the trigger didn't fire for you (timing bug, old schema), the second user got there first.

Fix. Open Supabase → Table Editorprofiles. Find your row. Change the role column to admin. Change the other user's role from admin back to the default (member or whatever your schema specifies). Save.

"Invalid JWT" errors after a while

Symptom. Logged-in users start getting "Invalid JWT" errors, usually after hours or days.

Cause. JWT expiration without automatic refresh. Normally the Supabase client refreshes silently; this can fail if a browser extension blocks the refresh request or if the refresh token is invalidated.

Fix.

  1. Ask the user to sign out and sign back in.
  2. If it's widespread, check Supabase → SettingsAuthenticationJWT Expiry — a very short expiry (< 1h) amplifies this.
  3. Confirm your Vercel deployment hasn't been set up behind a proxy that strips Supabase's cookies.

Email invites aren't being received

Symptom. You invited a team member but they never got the email.

Cause. Supabase's default email sender (noreply@mail.app.supabase.io) sometimes gets flagged by corporate spam filters.

Fix.

  1. Ask the invitee to check spam.
  2. Configure a custom SMTP server: Supabase → SettingsAuthenticationSMTP Settings. Point it at Resend, Postmark, SendGrid, or your workspace's email (requires SMTP credentials).
  3. Custom SMTP with your own domain has much better deliverability than the default.

Product-specific issues

Track — Boards don't render, infinite loading spinner

Symptom. The boards page shows a spinner forever. The browser network tab shows the boards query returning an empty array or erroring.

Cause. Most commonly: RLS policy on boards or team_members is blocking the query because your user isn't in the expected team.

Fix.

  1. Open the boards table in Supabase. If it's empty, you haven't created a board yet — click "Create board" in the UI.
  2. If boards exist but aren't showing: open team_members and confirm your profile_id is in there with the right team_id.
  3. If you were the first user and no team was created: run the seed SQL that creates a default team (see the Track README).

Track — Automation runner isn't firing

Symptom. You set up an automation but it doesn't run on matching events.

Cause. Either the Edge Function isn't deployed, the cron schedule isn't set, or the trigger condition doesn't match.

Fix.

  1. Supabase → Edge Functions → confirm track-automation-runner is listed and deployed.
  2. In Supabase SQL editor, run select * from cron.job where jobname like 'track%'; to confirm the schedule.
  3. Test manually: npx supabase functions invoke track-automation-runner and check the logs.

Comms — Messages aren't appearing in real-time

Symptom. You send a message and your collaborator doesn't see it until they refresh.

Cause. Supabase Realtime isn't enabled for the messages table, or the client subscription isn't set up.

Fix.

  1. Supabase → DatabaseReplication → enable Realtime for the messages table (and channel_members if channels are affected too).
  2. Restart the dev server / redeploy — changes to Realtime config don't apply to existing client connections.

Pulse — Slack integration posts nothing

Symptom. Standups finish but no Slack message appears in the configured channel.

Cause. Slack webhook URL is wrong, or the Edge Function lacks the SLACK_WEBHOOK_URL environment variable.

Fix.

  1. Test the webhook manually: curl -X POST -H 'Content-type: application/json' --data '{"text":"test"}' <webhook-url>. If that fails, the webhook is dead — regenerate it in Slack.
  2. Supabase → Edge Functionspulse-slack-webhookEnvironment Variables → confirm SLACK_WEBHOOK_URL is set.
  3. Check the function logs for the most recent invocation to see the actual error.

Ink — Documents save but don't sync across devices

Symptom. Editing a document on laptop saves, but reloading on phone shows the old version.

Cause. Document caching or Realtime not enabled for the blocks table.

Fix.

  1. Hard refresh both devices (Cmd+Shift+R / Ctrl+Shift+R).
  2. If still stale: enable Realtime on blocks and documents tables (same as Comms above).

License validation issues

"Invalid license" on production

Symptom. The deployed product shows a license error screen on first load.

Cause. Several possibilities:

  • License key was revoked (refund, manual revoke)
  • License key's bound domain doesn't match the current domain
  • License validation endpoint couldn't be reached (network issue)

Fix.

  1. Check your buyer dashboard: is the license marked active?
  2. Check the bound domain: does it match where you're deploying?
  3. If you deployed to a new domain, request a domain change from the dashboard (limit: 2 changes per year).
  4. If the validation endpoint is unreachable: the product is designed to fail open — it should allow access. If it isn't, there's a bug in the modified src/lib/license.js. See Platform Reference → Security.

Changed domains — now licenses fail

Symptom. You moved from my-crm.vercel.app to crm.mycompany.com and now the license errors.

Cause. The license was bound to the old domain on first validation.

Fix. Go to Dashboard → My Products → → Request Domain Change. Enter the new domain. This consumes one of your two annual domain changes.

AI customization issues

Claude Code isn't reading CLAUDE.md

Symptom. Claude Code's suggestions don't reference any of the ARK-specific conventions from CLAUDE.md.

Cause. You're probably not in the repo root when running claude, or CLAUDE.md has been accidentally renamed or moved.

Fix.

  1. pwd — confirm you're in the ARK repo root.
  2. ls CLAUDE.md — confirm it exists and isn't empty.
  3. Start the session with: "Read CLAUDE.md and summarize the three most important rules." If the summary doesn't match the file contents, the file isn't being read. Open an issue / contact Anthropic support.

AI tool keeps suggesting edits to src/lib/license.js

Symptom. You're working on an unrelated feature and the AI suggests "cleaning up" or modifying the license validator.

Cause. You're not reminding the AI of the guardrails, or CLAUDE.md isn't loaded in the current context.

Fix. At the top of every prompt that's going near sensitive code:

Do not modify src/lib/license.js or any fingerprint markers. These are called out as off-limits in CLAUDE.md.

If it keeps happening, start a fresh session and re-share CLAUDE.md.

Migration from AI-generated code fails

Symptom. The AI gave you a migration, you pasted it into Supabase, and it errored.

Cause. Common causes:

  • Wrong column type (e.g., integer when the existing foreign key is uuid)
  • Missing if not exists clause so re-runs fail
  • References a table or column name that doesn't exist

Fix.

  1. Copy the error message back into the AI session: "This migration failed with: <error>. Here's the current schema for the affected table: <paste from Supabase>. Fix the migration."
  2. Run the corrected version.

Generic "things are weird" debugging

When nothing else helps:

  1. Read the browser console — most frontend issues surface there first.
  2. Read the Vercel deployment logs — build errors and runtime errors from server functions appear here.
  3. Read the Supabase logs — Database → Logs shows query errors and RLS denials.
  4. Compare against a fresh deployment — if you've customized heavily, spin up a clean Vercel deploy from the pristine (non-fingerprinted) repo and confirm the issue doesn't happen there. If it doesn't, something in your customizations is the cause.
  5. Reset and retry — sometimes a broken dev state clears with rm -rf node_modules .next && npm install && npm run dev.

If nothing works, email support@arkteams.io with:

  • Which product and version
  • A clear description of what you did, what you expected, what happened
  • Any error messages (full stack trace, not just the first line)
  • Screenshots if UI-related

The more context you give us, the faster we can help.