relation "public.events" does not exist
What it means
Postgres raises "relation … does not exist" when a query references a table, view, or sequence that isn't visible on the current search_path — usually because it lives in another schema, hasn't been created yet, or the migration ran statements in the wrong order.
Why it happens
relation "public.events" does not exist (SQLSTATE 42P01) is Postgres telling you it looked for a table, view, materialized view, or sequence with that name and found nothing it could resolve. During a migration there are three common causes:
- Wrong schema / search_path. The object exists, but in a schema that isn't on the connection's
search_path. A query foreventsfails even thoughanalytics.eventsexists. - Order of operations. A statement references a table that a later statement creates — for example a foreign key or a view defined before its dependency. Postgres runs statements top-to-bottom and fails on the first forward reference.
- It really wasn't created. The table was made in the Supabase dashboard's SQL editor and never captured in a migration file, so replaying
supabase/migrations/never creates it on the destination.
How to fix it
First, confirm where (or whether) the object exists:
-- Every table and the schema it lives in
select schemaname, tablename
from pg_tables
where schemaname not in ('pg_catalog', 'information_schema')
order by schemaname, tablename;
If it exists in another schema, schema-qualify the reference or add the schema to the search_path:
-- Option A: fully qualify (preferred, unambiguous)
select * from analytics.events;
-- Option B: set the search_path for this session
set search_path to analytics, public;
If the statement order is the problem, create the table before anything that references it, or add the foreign key after both tables exist:
create table public.events (
id bigint generated always as identity primary key,
user_id uuid not null
);
-- add the FK only once both sides exist
alter table public.events
add constraint events_user_id_fkey
foreign key (user_id) references public.users (id);
If the table simply was never created on the destination, create it there — then reload PostgREST so the API sees it:
create table public.events ( /* … columns … */ );
notify pgrst, 'reload schema';
How to prevent it
- Always schema-qualify table names in migrations (
public.events, notevents) so they don't depend on the connection's search_path. - Keep DDL in migration files, not the dashboard SQL editor — objects created ad-hoc in the editor won't replay onto a new project.
- Order DDL by dependency: extensions → types → tables → foreign keys → indexes → views → policies. Add foreign keys and views only after their dependencies exist.
Frequently asked questions
- Does "relation does not exist" mean my table was deleted?
- No. It almost always means the table is not visible on the current search_path, or it hasn''t been created yet in this database. The data is not gone — the name just can''t be resolved from where the query is running.
- Why does it work in the Supabase SQL editor but fail in my migration?
- The SQL editor runs with a search_path that includes public, so unqualified names resolve. A migration or pooled connection may use a different search_path, so you must schema-qualify the name (public.events) or set the search_path explicitly.
- How do I list every table so I can check the exact name?
- Run "select schemaname, tablename from pg_tables where schemaname not in ('pg_catalog','information_schema');" to see every table and the schema it lives in.
Related errors