🎯

supabase-troubleshooting

🎯Skill

from adaptationio/skrillz

VibeIndex|
What it does

supabase-troubleshooting skill from adaptationio/skrillz

πŸ“¦

Part of

adaptationio/skrillz(191 items)

supabase-troubleshooting

Installation

Add MarketplaceAdd marketplace to Claude Code
/plugin marketplace add adaptationio/Skrillz
Install PluginInstall plugin from marketplace
/plugin install skrillz@adaptationio-Skrillz
Claude CodeAdd plugin in Claude Code
/plugin enable skrillz@adaptationio-Skrillz
Add MarketplaceAdd marketplace to Claude Code
/plugin marketplace add /path/to/skrillz
Install PluginInstall plugin from marketplace
/plugin install skrillz@local

+ 4 more commands

πŸ“– Extracted from docs: adaptationio/skrillz
1Installs
3
-
Last UpdatedJan 16, 2026

Skill Details

SKILL.md

Troubleshoot common Supabase issues including auth errors, RLS policies, connection problems, and performance. Use when debugging Supabase issues, fixing errors, or optimizing performance.

Overview

# 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"

```javascript

// Check email format

const { data, error } = await supabase.auth.signInWithPassword({

email: email.toLowerCase().trim(), // Normalize email

password

})

// Check if user exists

const { data } = await supabase

.from('auth.users') // Admin only

.select('*')

.eq('email', email)

```

"Email not confirmed"

```javascript

// Option 1: Resend confirmation

const { error } = await supabase.auth.resend({

type: 'signup',

email: 'user@example.com'

})

// Option 2: Admin confirm (server-side)

await supabaseAdmin.auth.admin.updateUserById(userId, {

email_confirm: true

})

```

"JWT expired"

```javascript

// Client auto-refreshes, but you can force it

const { data, error } = await supabase.auth.refreshSession()

// Listen for token refresh

supabase.auth.onAuthStateChange((event, session) => {

if (event === 'TOKEN_REFRESHED') {

// Update any cached tokens

}

})

```

Session Not Persisting

```javascript

// Check storage configuration

const supabase = createClient(url, key, {

auth: {

persistSession: true, // Default is true

storage: localStorage // Or custom storage

}

})

// Check for multiple instances

// Only create one Supabase client per app

```

Row Level Security (RLS) Issues

Empty Data Returned

```sql

-- Check if RLS is enabled

SELECT tablename, rowsecurity

FROM pg_tables

WHERE schemaname = 'public';

-- Check existing policies

SELECT * FROM pg_policies

WHERE tablename = 'your_table';

-- Test policy with your user ID

SET request.jwt.claims = '{"sub": "your-user-uuid", "role": "authenticated"}';

SELECT * FROM your_table;

```

"violates row-level security policy"

```javascript

// Check you're authenticated

const { data: { user } } = await supabase.auth.getUser()

console.log('Current user:', user?.id)

// Check the RLS policy requirements

// Common issue: auth.uid() doesn't match row's user_id

```

Debug RLS Policies

```sql

-- Enable detailed RLS debugging (temporary)

SET log_statement = 'all';

SET log_min_duration_statement = 0;

-- Test as specific user

SET request.jwt.claims = '{

"sub": "user-uuid",

"role": "authenticated",

"aal": "aal1"

}';

-- Run your query

SELECT * FROM posts;

-- Check auth functions

SELECT auth.uid();

SELECT auth.role();

SELECT auth.jwt();

```

RLS Performance Issues

```sql

-- Bad: Calls auth.uid() for each row

CREATE POLICY "slow" ON posts

USING (auth.uid() = user_id);

-- Good: Caches auth.uid() result

CREATE POLICY "fast" ON posts

USING ((SELECT auth.uid()) = user_id);

-- Add indexes for RLS columns

CREATE INDEX idx_posts_user_id ON posts(user_id);

```

Database Issues

"duplicate key value violates unique constraint"

```javascript

// Use upsert instead of insert

const { data, error } = await supabase

.from('table')

.upsert({ id: existingId, ...values }, {

onConflict: 'id'

})

.select()

```

"foreign key violation"

```javascript

// Ensure referenced row exists

const { data: parent } = await supabase

.from('parent_table')

.select('id')

.eq('id', parentId)

.single()

if (!parent) {

// Create parent first or handle error

}

```

Query Returning Stale Data

```javascript

// Disable cache for specific queries

const { data } = await supabase

.from('table')

.select('*')

.eq('id', id)

.single()

.throwOnError() // Actually throws on error

// Force fresh data

const { data } = await supabase

.from('table')

.select('*', { head: false, count: 'exact' })

```

Connection Issues

"Failed to fetch" / Network Error

```javascript

// Check Supabase URL

console.log('URL:', process.env.NEXT_PUBLIC_SUPABASE_URL)

// Check API key

console.log('Key prefix:', process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY?.slice(0, 20))

// Test connection

const { data, error } = await supabase.from('_health').select('*')

console.log('Health check:', { data, error })

```

Local Development Connection

```bash

# Check Docker is running

docker ps

# Check Supabase status

supabase status

# Restart if needed

supabase stop

supabase start

```

CORS Issues

```javascript

// Edge function must include CORS headers

const corsHeaders = {

'Access-Control-Allow-Origin': '*',

'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type'

}

// Always handle OPTIONS preflight

if (req.method === 'OPTIONS') {

return new Response('ok', { headers: corsHeaders })

}

```

Storage Issues

Upload Failing

```javascript

const { data, error } = await supabase.storage

.from('bucket')

.upload('path', file)

if (error) {

// Check error type

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

```sql

-- Check storage policies

SELECT * FROM pg_policies

WHERE tablename = 'objects'

AND schemaname = 'storage';

-- Common fix: Allow authenticated uploads to user folder

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)

```typescript

// Check for blocking operations

// Bad: Long synchronous operation

const result = heavyComputation()

// Good: Keep operations async and fast

const result = await heavyComputationAsync()

// Check limits:

// - CPU time: 2 seconds

// - Wall clock: 150s (400s on Pro)

```

Function Error (500)

```typescript

// Always wrap in try-catch

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

```bash

# Check secrets are set

supabase secrets list

# Set missing secrets

supabase secrets set API_KEY=value

# Note: Changes apply immediately, no redeploy needed

```

Realtime Issues

Not Receiving Events

```javascript

// 1. Check table has realtime enabled

// SQL: ALTER PUBLICATION supabase_realtime ADD TABLE your_table;

// 2. Check subscription status

const channel = supabase

.channel('test')

.on('postgres_changes', { event: '*', schema: 'public', table: 'posts' }, callback)

.subscribe((status, err) => {

console.log('Subscription status:', status, err)

})

// 3. Check RLS allows SELECT

// Realtime respects RLS policies

```

"Tried to subscribe multiple times"

```javascript

// Don't call subscribe() twice on same channel

const channel = supabase.channel('my-channel')

channel.subscribe() // OK

channel.subscribe() // Error!

// Cleanup before resubscribing

await supabase.removeChannel(channel)

const newChannel = supabase.channel('my-channel').subscribe()

```

Too Many Connections

```javascript

// Clean up channels on unmount

useEffect(() => {

const channel = supabase.channel('data')

.on('postgres_changes', {...}, callback)

.subscribe()

return () => {

supabase.removeChannel(channel) // Important!

}

}, [])

```

Performance Optimization

Slow Queries

```sql

-- Use EXPLAIN ANALYZE to find bottlenecks

EXPLAIN ANALYZE SELECT * FROM posts WHERE user_id = 'uuid';

-- Add missing indexes

CREATE INDEX CONCURRENTLY idx_posts_user_id ON posts(user_id);

-- Check for sequential scans

SELECT relname, seq_scan, idx_scan

FROM pg_stat_user_tables

ORDER BY seq_scan DESC;

```

High Connection Count

```bash

# Check connections

supabase inspect db role-connections --linked

# Use connection pooling for serverless

# Use transaction mode, not session mode

```

Optimize RLS Queries

```sql

-- Avoid subqueries in hot path

-- Bad:

USING (user_id IN (SELECT user_id FROM team_members WHERE team_id = ...))

-- Good: Use security definer function

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

  • [common-errors.md](references/common-errors.md) - Error code reference