Storage: upload rejected with RLS violation that no policy can satisfy (TO public also fails) #50714
|
SUBJECT SUMMARY All uploads to our Storage bucket have failed since 23 April 2026 with IMPACT Logo, digital signature and payment QR upload are all non-functional and ENVIRONMENT Project ref mjrbytfvesgvbuxyoidp (Free tier) REPRODUCTION POST /storage/v1/object/professional-assets/logos/--cropped.png Response 400: Failing request timestamp (UTC): Last successful uploads: 23 April 2026, four objects written between ELIMINATED — CLIENT SIDE Authorization header present and correct on the actual failing request Token claims decoded at time of failure: Reproduced on a token seconds old after a hard reload — identical failure, ELIMINATED — DATABASE SIDE Three INSERT policies tested on storage.objects, each retried against the The anon and public policies were temporary and have been dropped. Schema state, read from the catalog: Bucket professional-assets exists, is public, and the request path and WHY WE BELIEVE THIS IS SERVICE-SIDE A committed policy of permits the row for every ordinary PostgreSQL role. The predicate matched WHAT WE ARE ASKING FOR
NOTES The in-dashboard AI assistant triaged this first and reached the same No credentials are included in this report and none should be needed. We |
Replies: 1 comment 1 reply
|
The root cause of this failure is that PostgreSQL requires a matching Why PostgreSQL Rejects the Insert with an RLS ViolationWhen INSERT INTO storage.objects (bucket_id, name, owner, metadata, version, ...)
VALUES ($1, $2, $3, $4, $5, ...)
RETURNING *;In PostgreSQL, Row-Level Security evaluation rules dictate that when an
Because you tested and verified only How to FixAdd a corresponding -- 1. Ensure the SELECT policy exists so the RETURNING clause succeeds
CREATE POLICY "Allow authenticated read professional-assets"
ON storage.objects
FOR SELECT
TO authenticated
USING (bucket_id = 'professional-assets');
-- 2. Ensure the INSERT policy is scoped as desired
CREATE POLICY "Allow authenticated upload professional-assets"
ON storage.objects
FOR INSERT
TO authenticated
WITH CHECK (bucket_id = 'professional-assets');If your bucket is public and unauthenticated visitors also need to view the files via the public CDN URL or read metadata, you can scope the CREATE POLICY "Allow public read professional-assets"
ON storage.objects
FOR SELECT
TO public
USING (bucket_id = 'professional-assets');VerificationOnce the |
The root cause of this failure is that PostgreSQL requires a matching
SELECTpolicy onstorage.objectsduring anINSERT ... RETURNINGoperation, even when yourINSERTpolicy is completely satisfied.Why PostgreSQL Rejects the Insert with an RLS Violation
When
supabase-jsuploads an object viaPOST /storage/v1/object/..., the Supabase Storage backend (storage-api) writes the binary payload to storage and then persists the metadata record to PostgreSQL by executing:In PostgreSQL, Row-Level Security evaluation rules dictate that when an
INSERTstatement includes aRETU…