The PGRST100 error occurs when Supabase (PostgREST API) cannot find the table you're trying to access. This can happen when the table is in a different schema, has a case-sensitivity issue, doesn't exist yet, or when the PostgREST schema cache hasn't been refreshed.
PostgREST is the REST API layer that Supabase uses to expose your PostgreSQL database. The PGRST100 error indicates that PostgREST tried to access a relation (table) that doesn't exist or isn't accessible at the current schema level. This is distinct from the PostgreSQL 42P01 error, though they have similar root causes. PGRST-prefixed errors come from PostgREST's own query parsing and schema interpretation layer, while 42P01 comes directly from PostgreSQL. The most common cause is attempting to access a table that either: 1. Doesn't exist in your database 2. Exists in a non-public schema without proper schema qualification 3. Has never been created 4. Was recently created but the PostgREST schema cache hasn't been reloaded
First, confirm the table actually exists in PostgreSQL:
1. Open Supabase Dashboard > SQL Editor
2. Run this query to list all tables:
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name;3. Look for your table in the results. If it's not there, the table doesn't exist yet and you need to create it:
CREATE TABLE your_table (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);4. After creating the table, enable Row Level Security (RLS) in the Supabase dashboard by clicking the table and toggling RLS on
5. Add a simple policy to allow SELECT:
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow public read" ON your_table
FOR SELECT USING (true);Table names are case-sensitive if they were created with quotes. Verify spelling:
1. In Supabase Dashboard, go to the Table Editor
2. Look at your table name exactly as it appears (e.g., users, Users, my_table)
3. Use that exact name (with correct case) in your queries:
// If table is named 'users' (lowercase)
const { data, error } = await supabase
.from('users') // Must match exactly
.select();
// If table is named 'Users' (capitalized)
const { data, error } = await supabase
.from('Users') // Must match exactly
.select();If your table was created with CREATE TABLE "MyTable", always use the exact casing in queries.
If you just created a table and PostgREST hasn't detected it yet, the schema cache needs to refresh:
1. Option A - Quick Fix: Restart your Supabase instance by clicking the "Restart" button in Supabase Dashboard > Settings > API Settings
2. Option B - Wait for Auto-Refresh: PostgREST automatically refreshes its schema cache every 1-5 minutes, so waiting a moment might solve it
3. Option C - Re-deploy: In Supabase Cloud, the instance restarts automatically on schema changes, but if using self-hosted PostgREST, you'll need to restart it
# If self-hosted, restart PostgREST
docker restart postgrest_container_name
# or
systemctl restart postgrestAfter restarting, your new table should be accessible via the REST API.
If your table is in a schema other than 'public', you must specify the schema:
1. First, ensure the custom schema is exposed to the Supabase API:
-- In Supabase SQL Editor, add the schema to exposed schemas
SELECT net.http_get('http://localhost:3000/api/schema')
-- Or manually verify PostgREST config includes your schema2. In your Supabase client, use the .schema() method:
const { data, error } = await supabase
.schema('my_custom_schema') // Specify non-public schema
.from('my_table')
.select();3. If you get a 42501 "permission denied" error after this, you need to grant permissions:
GRANT USAGE ON SCHEMA my_custom_schema TO authenticated;
GRANT SELECT ON ALL TABLES IN SCHEMA my_custom_schema TO authenticated;Tables need RLS enabled and policies configured to be accessible via the REST API:
1. In Supabase Dashboard, go to Authentication > Policies
2. For each table, click and enable RLS
3. Add at least one policy to allow access:
-- Allow authenticated users to read all rows
CREATE POLICY "Enable read access for authenticated users"
ON your_table FOR SELECT
TO authenticated
USING (true);
-- Allow authenticated users to insert
CREATE POLICY "Enable insert for authenticated users"
ON your_table FOR INSERT
TO authenticated
WITH CHECK (true);
-- Allow authenticated users to update their own data
CREATE POLICY "Enable update for users based on id"
ON your_table FOR UPDATE
TO authenticated
USING (auth.uid() = user_id);Without RLS policies, even though the table exists, the REST API won't be able to access it.
Ensure your Supabase client is properly initialized with correct URL and API key:
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL, // Must be valid
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY // Must be valid anon key
);
// Verify connection works
const { data: { tables } } = await supabase
.from('information_schema.tables')
.select('table_name')
.eq('table_schema', 'public');
console.log('Available tables:', tables);If the client isn't initialized with correct credentials, it might not be connecting to the right database at all.
PostgREST vs PostgreSQL Errors: While PostgreSQL returns 42P01 for "relation does not exist", PostgREST returns PGRST100 when it encounters the same issue at the REST API layer. The underlying cause is usually the same, but PGRST100 indicates PostgREST is the component reporting the error.
Schema Cache Mechanics: PostgREST maintains an in-memory cache of your database schema (table names, columns, types, etc.). When you create a new table, PostgREST won't see it until the cache refreshes. In Supabase Cloud, this typically happens automatically within 1-5 minutes or on restart. Self-hosted PostgREST requires manual schema cache clearing.
RLS and REST API Access: A common gotcha is that even if a table exists and is spelled correctly, the REST API can't access it without proper RLS policies. This is a security feature—rows are hidden by default until you explicitly grant access via policies.
Debugging Tips:
1. Always check the Supabase SQL Editor first to verify the table exists
2. Use information_schema queries to check table existence programmatically
3. Look at PostgREST logs if self-hosted: they often show the exact table name it's looking for
4. When copying SQL from tutorials, be mindful of schema prefixes and case sensitivity
email_address_not_authorized: Email sending to this address is not authorized
Email address not authorized for sending in Supabase Auth
reauthentication_needed: Reauthentication required for security-sensitive actions
Reauthentication required for security-sensitive actions
no_authorization: No authorization header was provided
How to fix "no authorization header was provided" in Supabase
otp_expired: OTP has expired
How to fix 'otp_expired: OTP has expired' in Supabase
bad_oauth_state: OAuth state parameter is missing or invalid
How to fix 'bad_oauth_state: OAuth state parameter missing' in Supabase