Supabase Troubleshooting Skill
Debug and fix common Supabase issues.
Quick Diagnosis
| Symptom |
Likely Cause |
| Empty data returned |
RLS policies blocking access |
| "Not authorized" |
Missing or invalid auth token |
| "JWT expired" |
Token needs refresh |
| Slow queries |
Missing indexes or RLS subqueries |
| Connection refused |
Wrong URL or service down |
| "Duplicate key" |
Unique constraint violation |
| Function timeout |
Cold start or heavy computation |
Authentication Issues
"Invalid login credentials"
const { data, error } = await supabase.auth.signInWithPassword({
email: email.toLowerCase().trim(),
password
})
const { data } = await supabase
.from('auth.users')
.select('*')
.eq('email', email)
"Email not confirmed"
const { error } = await supabase.auth.resend({
type: 'signup',
email: 'user@example.com'
})
await supabaseAdmin.auth.admin.updateUserById(userId, {
email_confirm: true
})
"JWT expired"
const { data, error } = await supabase.auth.refreshSession()
supabase.auth.onAuthStateChange((event, session) => {
if (event === 'TOKEN_REFRESHED') {
}
})
Session Not Persisting
const supabase = createClient(url, key, {
auth: {
persistSession: true,
storage: localStorage
}
})
Row Level Security (RLS) Issues
Empty Data Returned
SELECT tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public';
SELECT * FROM pg_policies
WHERE tablename = 'your_table';
SET request.jwt.claims = '{"sub": "your-user-uuid", "role": "authenticated"}';
SELECT * FROM your_table;
"violates row-level security policy"
const { data: { user } } = await supabase.auth.getUser()
console.log('Current user:', user?.id)
Debug RLS Policies
SET log_statement = 'all';
SET log_min_duration_statement = 0;
SET request.jwt.claims = '{
"sub": "user-uuid",
"role": "authenticated",
"aal": "aal1"
}';
SELECT * FROM posts;
SELECT auth.uid();
SELECT auth.role();
SELECT auth.jwt();
RLS Performance Issues
CREATE POLICY "slow" ON posts
USING (auth.uid() = user_id);
CREATE POLICY "fast" ON posts
USING ((SELECT auth.uid()) = user_id);
CREATE INDEX idx_posts_user_id ON posts(user_id);
Database Issues
"duplicate key value violates unique constraint"
const { data, error } = await supabase
.from('table')
.upsert({ id: existingId, ...values }, {
onConflict: 'id'
})
.select()
"foreign key violation"
const { data: parent } = await supabase
.from('parent_table')
.select('id')
.eq('id', parentId)
.single()
if (!parent) {
}
Query Returning Stale Data
const { data } = await supabase
.from('table')
.select('*')
.eq('id', id)
.single()
.throwOnError()
const { data } = await supabase
.from('table')
.select('*', { head: false, count: 'exact' })
Connection Issues
"Failed to fetch" / Network Error
console.log('URL:', process.env.NEXT_PUBLIC_SUPABASE_URL)
console.log('Key prefix:', process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY?.slice(0, 20))
const { data, error } = await supabase.from('_health').select('*')
console.log('Health check:', { data, error })
Local Development Connection
docker ps
supabase status
supabase stop
supabase start
CORS Issues
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type'
}
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
}
Storage Issues
Upload Failing
const { data, error } = await supabase.storage
.from('bucket')
.upload('path', file)
if (error) {
if (error.message.includes('exceeded')) {
console.log('File too large')
} else if (error.message.includes('mime type')) {
console.log('Invalid file type')
} else if (error.message.includes('row-level security')) {
console.log('RLS policy blocking upload')
}
}
Storage RLS Debug
SELECT * FROM pg_policies
WHERE tablename = 'objects'
AND schemaname = 'storage';
CREATE POLICY "Upload to own folder"
ON storage.objects FOR INSERT
TO authenticated
WITH CHECK (
bucket_id = 'uploads'
AND auth.uid()::text = (storage.foldername(name))[1]
);
Edge Function Issues
Function Timeout (504)
const result = heavyComputation()
const result = await heavyComputationAsync()
Function Error (500)
try {
const result = await riskyOperation()
return new Response(JSON.stringify({ data: result }))
} catch (error) {
console.error('Function error:', error)
return new Response(
JSON.stringify({ error: error.message }),
{ status: 500 }
)
}
Secrets Not Available
supabase secrets list
supabase secrets set API_KEY=value
Realtime Issues
Not Receiving Events
const channel = supabase
.channel('test')
.on('postgres_changes', { event: '*', schema: 'public', table: 'posts' }, callback)
.subscribe((status, err) => {
console.log('Subscription status:', status, err)
})
"Tried to subscribe multiple times"
const channel = supabase.channel('my-channel')
channel.subscribe()
channel.subscribe()
await supabase.removeChannel(channel)
const newChannel = supabase.channel('my-channel').subscribe()
Too Many Connections
useEffect(() => {
const channel = supabase.channel('data')
.on('postgres_changes', {...}, callback)
.subscribe()
return () => {
supabase.removeChannel(channel)
}
}, [])
Performance Optimization
Slow Queries
EXPLAIN ANALYZE SELECT * FROM posts WHERE user_id = 'uuid';
CREATE INDEX CONCURRENTLY idx_posts_user_id ON posts(user_id);
SELECT relname, seq_scan, idx_scan
FROM pg_stat_user_tables
ORDER BY seq_scan DESC;
High Connection Count
supabase inspect db role-connections --linked
Optimize RLS Queries
USING (user_id IN (SELECT user_id FROM team_members WHERE team_id = ...))
CREATE FUNCTION get_user_teams()
RETURNS SETOF uuid
LANGUAGE sql STABLE SECURITY DEFINER
AS $$ SELECT team_id FROM team_members WHERE user_id = auth.uid() $$;
USING (team_id IN (SELECT get_user_teams()))
Common Error Codes
PostgREST Errors (PGRST*)
| Code |
Description |
Solution |
PGRST116 |
No rows found (single expected) |
Use maybeSingle() instead of single() |
PGRST205 |
Table not found in schema cache |
Check table name spelling, verify table exists |
PGRST301 |
Multiple rows (single expected) |
Add unique constraint or better filter |
PostgreSQL Errors
| Code |
Description |
Solution |
22P02 |
Invalid input syntax (e.g., bad UUID) |
Validate input format before query |
23503 |
Foreign key violation |
Ensure parent row exists first |
23505 |
Unique constraint violation |
Use upsert or check existence |
42501 |
Insufficient privilege (RLS) |
Fix RLS policies or use service role |
42703 |
Column does not exist |
Check column name spelling |
42P01 |
Relation (table) doesn't exist |
Check table name and schema |
08P01 |
Protocol violation |
Check query syntax |
Auth Errors
| Error |
Description |
Solution |
Invalid API key |
Wrong or missing apikey header |
Check SUPABASE_ANON_KEY |
JWT expired |
Access token expired |
Call refreshSession() |
Invalid login credentials |
Wrong email/password |
Verify credentials |
References