Saltar al contenido principal
Supabase

Supabase: new row violates row-level security policy for table

Cómo solucionar el error de Row Level Security (RLS) en Supabase. Configurar políticas RLS correctamente para INSERT, SELECT, UPDATE y DELETE.

Error: new row violates row-level security policy for table

¿Por qué ocurre?

Supabase bloquea la operación porque: - La tabla tiene Row Level Security (RLS) activado pero no hay políticas que permitan la operación - La política existe pero no aplica al usuario actual (anon vs authenticated) - Falta la cláusula `auth.uid() = user_id` en la política - Estás usando la clave `anon` (pública) para insertar en una tabla que solo permite usuarios autenticados - La política de INSERT no coincide con la de SELECT (dos políticas separadas)

Solución paso a paso

1. Diagnóstico: ver las políticas actuales

-- En Supabase SQL Editor
SELECT schemaname, tablename, policyname, cmd, qual, with_check
FROM pg_policies
WHERE tablename = 'tu_tabla';

2. Política básica para usuarios autenticados

-- Permitir que cada usuario vea solo sus propios datos
CREATE POLICY "users_select_own" ON public.posts
  FOR SELECT
  USING (auth.uid() = user_id);

-- Permitir que usuarios autenticados inserten sus propios datos CREATE POLICY "users_insert_own" ON public.posts FOR INSERT WITH CHECK (auth.uid() = user_id);

-- Permitir actualizar solo sus propios datos CREATE POLICY "users_update_own" ON public.posts FOR UPDATE USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);

-- Permitir borrar solo sus propios datos CREATE POLICY "users_delete_own" ON public.posts FOR DELETE USING (auth.uid() = user_id);

3. Política para contenido público (lectura sin auth)

-- Cualquiera puede leer posts publicados
CREATE POLICY "public_read_published" ON public.posts
  FOR SELECT
  USING (published = true);

-- Solo autenticados pueden crear CREATE POLICY "auth_insert" ON public.posts FOR INSERT TO authenticated WITH CHECK (true);

4. Usar service_role key para operaciones admin (bypass RLS)

// ⚠️ Solo en el servidor, nunca en el cliente
import { createClient } from '@supabase/supabase-js'

const supabaseAdmin = createClient( process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY // ← bypasea RLS )

// En una API route / server action const { data, error } = await supabaseAdmin .from('posts') .insert({ title: 'Admin post', user_id: userId })

5. Desactivar RLS temporalmente (solo para desarrollo)

-- ⚠️ SOLO en desarrollo/testing
ALTER TABLE public.posts DISABLE ROW LEVEL SECURITY;

-- Reactivar ALTER TABLE public.posts ENABLE ROW LEVEL SECURITY;

6. Verificar usuario autenticado en el cliente

const { data: { user } } = await supabase.auth.getUser()
console.log('Usuario:', user?.id) // null si no está autenticado

// Asegurarse de incluir el token en las requests const supabase = createClient(url, anonKey, { auth: { persistSession: true, autoRefreshToken: true, } })

Cómo evitarlo en el futuro

- Activa RLS en TODAS las tablas desde el principio, no como afterthought - En Supabase Dashboard hay un "RLS Advisor" que sugiere políticas automáticamente - Nunca uses la `service_role` key en código de cliente (frontend) - Prueba las políticas con la función `auth.uid()` en el SQL Editor con distintos usuarios - El "Policy Tester" de Supabase Dashboard permite simular operaciones como distintos usuarios

SupabaseRLSPostgreSQLseguridadpolíticas

¿Quieres que una IA te ayude? Genera el prompt perfecto para tu error:

Generador de Prompts

¿Necesitas desarrollo a medida?

Apps web, IA, módulos ERP — cuéntame tu proyecto.