A hallucinated RPC function name is more disruptive than a hallucinated table name: Supabase .rpc() calls to non-existent functions return a PostgREST 404 error immediately rather than an empty result set, causing hard failures in dashboards, analytics, and any server action that delegates business logic to the database. This is a reference-integrity gap (OWASP A08) specific to Supabase projects where the AI correctly patterns the .rpc() call but invents the function name. Unlike missing tables, there is no partial fallback — the entire call fails, and the error message (function get_dashboard_data() does not exist) requires knowing to look in migration SQL to diagnose.
Critical because RPC calls to non-existent functions fail with an immediate 404 error — there is no silent fallback, and every caller of that code path is broken at runtime.
Verify the function name against your migration SQL, then either fix the call to match an existing function or create the missing function in a new migration.
-- supabase/migrations/042_add_dashboard_rpc.sql
CREATE OR REPLACE FUNCTION public.get_dashboard_data(p_user_id UUID)
RETURNS TABLE (metric TEXT, value BIGINT) AS $$
BEGIN
RETURN QUERY
SELECT 'submissions'::TEXT, COUNT(*)::BIGINT
FROM submissions
WHERE user_id = p_user_id;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
Apply with supabase db push. The function name in .rpc('get_dashboard_data') must match the CREATE FUNCTION public.get_dashboard_data name exactly — Supabase strips the public. prefix in RPC calls. Run supabase gen types typescript after adding the function to get type-checked RPC argument validation.
ID: ai-slop-hallucinations.data-references.db-rpc-functions-exist
Severity: critical
What to look for: Walk source files for .rpc('function_name', ...) and .rpc("function_name", ...) calls on the Supabase client. Extract the function name string literal from the first argument. Then verify each function name exists in KNOWN_FUNCTIONS (built from migration SQL in step 8 — all CREATE [OR REPLACE] FUNCTION [public.]function_name(...) statements, with public. prefix stripped). Count all .rpc() calls inspected, total resolved, total unresolved.
Pass criteria: 100% of .rpc() function name arguments resolve to a function defined in migration SQL. Report: "X .rpc() calls inspected, Y resolved, 0 unresolved."
Fail criteria: At least 1 .rpc() call references a function not defined in the migration files.
Do NOT pass when: The function name is dynamically computed (.rpc(fnName) where fnName is a variable) — flag as "dynamic RPC name" with detail.
Skip (N/A) when: No @supabase/supabase-js in dependencies, OR no .rpc() calls found in source files, OR no migration files exist in supabase/migrations/.
Report even on pass: Report the count. Example: "3 .rpc() calls inspected, 3 resolved against 24 functions defined in migrations (100%)."
Detail on fail: "1 unresolved RPC reference: supabase.rpc('get_dashboard_data') in src/lib/analytics.ts — function 'get_dashboard_data' not found in supabase/migrations/. Available functions: get_segment_scores, get_total_issues_caught, increment_scrab_plays, ..."
Remediation: A hallucinated RPC function name causes Supabase to return a 404 error at runtime. Unlike table references (which may return empty data), RPC calls to non-existent functions fail loudly. Fix the function name to match a defined function, or create the missing function in a new migration:
-- supabase/migrations/042_add_dashboard_rpc.sql
CREATE OR REPLACE FUNCTION public.get_dashboard_data(p_user_id UUID)
RETURNS TABLE (/* ... */) AS $$
BEGIN
-- implementation
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
Run supabase db push to apply the migration, then verify the RPC works with supabase functions invoke.