Home / RLS / Fix PGRST200: Could not find a relationship · Em português

Supabase · Error fix

Fix PGRST200: Could not find a relationship in the schema cache

Postgres 15 · Supabase✓ code tested against a real database
TL;DR

Joining tables inside select() (embedding) works only through a foreign key. No foreign key between the two tables, no relationship. Add the foreign key (the referenced column must be a primary key or unique), reload the cache, and if there are two keys between the same tables, name the one you mean.

01 What the error says

response

{
  "code": "PGRST200",
  "message": "Could not find a relationship between 'books' and 'authors' in the schema cache",
  "details": "Searched for a foreign key relationship between 'books' and 'authors' in the schema 'public', but no matches were found."
}

A query like supabase.from('books').select('title, authors(name)') asks the Data API to join through a foreign key. It doesn't guess joins from column names: author_id alone isn't enough.

02 Check which foreign keys exist

check.sql

select conrelid::regclass as from_table, confrelid::regclass as to_table, conname
from pg_constraint
where contype = 'f' and connamespace = 'public'::regnamespace
order by 1;

03 Add the foreign key

migration.sql

alter table public.books
  add constraint books_author_id_fkey
  foreign key (author_id) references public.authors(id);

notify pgrst, 'reload schema';

The referenced column must be a primary key or unique, otherwise Postgres refuses the constraint (there is no unique constraint matching given keys).

04 Two keys between the same tables: PGRST201

If books has both author_id and editor_id pointing to authors, the embed is ambiguous and you get PGRST201, whose hint lists the options. Name the foreign key:

// pick the relationship by constraint name
supabase.from('books').select('title, author:authors!books_author_id_fkey(name)')

05 Found, but the joined rows are empty

That's RLS, not the relationship: the embedded table has its own policies, and rows the caller can't see come back as null or an empty array. Check the SELECT policy on the joined table.

◆ FREE · 30 SECONDS · NO SIGNUP

Is your app leaking right now?

Paste your live URL. The scanner reads your page and its JavaScript for a Supabase service_role key, the one leak that skips every policy in this guide.

◆ FREE · MIT · npm + GitHub Action

Catch this before it ships

airlock-rls is a CI gate that fails your build when a table ships exposed or a policy is permissive: the same class of bug, caught in CI against a database with your migrations applied, before it reaches prod.

npx airlock-rls→

Or start from nextjs-supabase-starter : auth + a table with RLS + an isolation test, so you start from a pattern that's already sealed.

FREE PDF

Grab the Supabase RLS cheat sheet

The golden rules, the footguns that leak in prod, correct policy snippets, and the isolation test — on one page.

FAQ

Can I join tables that are in different schemas?

The foreign key can point across schemas, but both tables have to be in schemas the Data API exposes for the embed to work.

I added the foreign key and still get PGRST200.

Reload the schema cache (notify pgrst, 'reload schema'), and check the table names in the select: the embed uses table names (or the alias you give it), not column names.