Home / RLS / Fix PGRST202: Could not find the function · Em português

Supabase · Error fix

Fix PGRST202: Could not find the function in the schema cache

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

The Data API looks a function up by name and by the names of the arguments you send. If you call rpc('get_orders', { userId }) and the function's parameter is p_user_id, it isn't found. Send the exact parameter names, keep the function in an exposed schema, and reload the cache after creating it.

01 Read the message

response

{
  "code": "PGRST202",
  "message": "Could not find the function public.get_orders(userId) in the schema cache"
}

The parentheses list the argument names your client sent, not the function's. Compare them with the definition: that mismatch is the most common cause. HTTP status is 404.

02 The causes

CAUSE 1 · most common

Argument names don't match

RPC arguments are matched by name. The function below must be called with p_user_id, not userId or user_id.

CAUSE 2

The function isn't in an exposed schema

Only schemas listed in the Data API settings are served. A function in private is invisible to rpc(), which is usually what you want for helpers.

CAUSE 3

A stale cache

The function was just created or its signature changed.

function and call

create function public.get_orders(p_user_id uuid)
returns setof orders language sql stable as $$
  select * from public.orders where user_id = p_user_id
$$;

-- client: the key must be the parameter name
-- await supabase.rpc('get_orders', { p_user_id: user.id })

notify pgrst, 'reload schema';   -- after creating or changing it

03 The error you'll hit next: permissions

Once it's found, the caller's role needs execute, or the error becomes 42501 permission denied for function get_orders. Grant only the roles that should call it:

revoke execute on function public.get_orders(uuid) from public, anon;
grant execute on function public.get_orders(uuid) to authenticated;

New functions are executable by everyone by default (Postgres grants execute to public), so revoke first if the function shouldn't be public. A security definer function bypasses RLS: list the ones anon can call.

04 Two functions with the same name

Overloads that differ only in types give a different error, PGRST203 Could not choose the best candidate function. Rename one or give the parameters different names.

◆ 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

It works in the SQL editor. Why not through rpc()?

The SQL editor calls the function directly with positional or named arguments and as a privileged role. rpc() goes through the Data API, which matches by argument names, only sees exposed schemas, and runs as anon or authenticated.

Does the order of the arguments matter?

No. The Data API matches arguments by name, so order doesn't matter, but every name has to exist in the function's parameter list.