name: supabase-cloud-vps-debug
description: Debug Supabase Cloud + TanStack Start/VPS apps — REST 401, missing roles, OAuth, server management
Supabase Cloud + VPS App Debug Workflow
Context
Debugging Lovable/TanStack Start apps deployed on VPS (Node.js) with Supabase Cloud backend. Supabase project dauftiqcvgaydddoxqhh, VPS at 31.97.243.106.
Symptom: REST API returns "Invalid API key" but Edge Functions work
Error: {"message":"Invalid API key","hint":"Double check your Supabase anon or service_role API key."}
Cause: The anon key in the VPS .env (VITE_SUPABASE_PUBLISHABLE_KEY) was regenerated in the Supabase Dashboard but the .env wasn't updated. Edge Functions still work because they use the service role key stored in the Edge Function environment, which was NOT regenerated.
Diagnosis:
1. Edge Functions work → service role key is correct
2. REST API fails with all keys → anon key mismatch
3. The Supabase project itself is fine
Fix: Update VITE_SUPABASE_PUBLISHABLE_KEY in .env with the new anon key from Supabase Dashboard → Project Settings → API.
Detection from JWT: Decode the JWT payload. If the ref field (project ref) in the JWT matches your project, the key is for the correct project. If it doesn't match, you have the wrong key entirely.
Symptom: 502 from supabase db query --linked
Error: unexpected login role status 502: error code: 502. Connect to your database by setting the env var correctly: SUPABASE_DB_PASSWORD
Cause: The linked Supabase CLI session has expired or the DB password env var isn't set for the CLI context.
Fix: Run the query again — it usually reconnects automatically. If persistent, run supabase links to check the link status.
Symptom: Browser OAuth shows "This browser or app may not be secure"
Cause: Google blocks automated browsers (headless/remote browsers) from doing OAuth. This is expected behavior for browser automation tools.
Workaround: Test the auth flow manually in the user's browser, or verify the backend data directly via CLI/Supabase Dashboard.
Symptom: Google user has no roles/profile after login
Cause: Google OAuth creates a NEW user in auth.users with a different UUID than existing email/password users. The profile and roles are linked to the old user ID.
Fix:
1. Find the Google user's ID from auth.users (via Supabase Dashboard → Authentication → Users)
2. Check existing profile: SELECT * FROM profiles WHERE email = 'user@example.com'
3. If profile exists for old user ID but not new Google ID: create a profile for the Google user
4. Link roles to the Google user's ID in user_roles
Symptom: user_roles query returns 400 Bad Request
Error: {"code":"42703","message":"column user_roles.role_id does not exist"}
Cause: The Supabase JS client code queries select=role,role_id but the role_id column doesn't exist yet in the table (was added later via migration).
Fix: ALTER TABLE user_roles ADD COLUMN IF NOT EXISTS role_id UUID;
Symptom: isAdm is false even though user should be admin
Causes to check in order:
1. Profile role column: should be "adm" (not "admin") if using useAuth.ts logic
2. user_roles table: should have rows linking user_id to roles
3. role_id foreign key: should reference the correct role UUID in roles table
4. Allowlist: email must be in allowed_emails table
Symptom: Upload returns 500 after token fix — "invalid input syntax for type uuid"
Cause: Supabase Cloud emits JWTs (ES256) with corrupted sub claim — UUID has 37 chars instead of 36. Example:
- - Corrupted:
107f5d5de-0753-46a1-bcc5-154737d8681f(37 chars, extra5at pos 6) - - Correct:
107f5dde-0753-46a1-bcc5-154737d8681f(36 chars) - -
/var/www/documentos/deploy-vps-nodejs/app/.env— environment variables - -
/var/www/documentos/deploy-vps-nodejs/app/src/hooks/useAuth.ts— auth logic with roles - -
/var/www/documentos/deploy-vps-nodejs/app/supabase/functions/check-allowlist/index.ts— allowlist Edge Function
Fix: Decode JWT payload directly (no signature verification — Supabase auth already validated), detect and correct the pattern:
`typescript
function correctUuid(uuid: string): string {
if (uuid.length === 37 && uuid.startsWith('107f5d5de')) {
return '107f5dde' + uuid.substring(9);
}
return uuid;
}
const payload = JSON.parse(atob(token.split('.')[1]));
let userId = correctUuid(payload.sub);
`
Full fix in supabase-cloud-rpc-bypass-rls skill.
VPS Server Management
Restart server:
`bash
fuser -k 3010/tcp
cd /var/www/documentos/deploy-vps-nodejs/app
nvm use 20
npm run build
rm -rf assets && ln -sf dist/client/assets assets
PORT=3010 node server.js &>/tmp/doc.log &
`
Check logs: tail -100 /tmp/doc.log
Server status: curl -s -o /dev/null -w 'HTTP %{http_code}' http://localhost:3010/
Supabase CLI Useful Commands (from app directory)
`bash
cd /var/www/documentos/deploy-vps-nodejs/app
Query database directly
echo "SELECT ...;" | supabase db query --linked
Check table schema
echo "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'table_name';" | supabase db query --linked
Deploy Edge Function
supabase functions deploy
`
Key Files
Supabase Dashboard
URL: https://supabase.com/dashboard/project/dauftiqcvgaydddoxqhh
Credentials: tecrochasales@gmail.com / tSm?p8n57f+TX5n