The 'Error 400: Bad Request' in Supabase means the server rejected your request due to invalid parameters, malformed data, or schema mismatches. Common causes include sending data that does not match the table schema, using .single() on queries that return zero or multiple rows, and malformed PostgREST filter syntax. Check your query against the actual table schema in the Supabase dashboard.
What does "Error 400: Bad Request" mean in Supabase?
When Supabase returns HTTP 400, the PostgREST API or Edge Function could not process your request because something in the request itself is wrong. Unlike a 500 error (server failure) or 403 (permission denied), a 400 means the request format, parameters, or data do not match what the server expects.
The most confusing 400 error in Supabase is PGRST116: "JSON object requested, multiple (or no) rows returned." This occurs when you use .single() and the query returns 0 or more than 1 row. The fix is to use .maybeSingle() when zero results are possible. This error is extremely common in AI-generated code because AI tools default to .single() without considering edge cases.
Another frequent 400 is PGRST200: "Could not find a relationship between 'TABLE_A' and 'TABLE_B' in the schema cache." This happens when PostgREST's cached schema is out of date after you add new tables or foreign keys. The fix is to reload the schema cache by running NOTIFY pgrst, 'reload schema' in the SQL editor.
Common causes
Using .single() on a query that
returns zero rows or multiple rows (PGRST116 error)
Sending data with column names or
types that do not match the table schema (misspelled columns, wrong data types)
PostgREST's schema cache is stale
and does not reflect recent table or relationship changes (PGRST200)
Malformed filter syntax in PostgREST
query parameters (incorrect operators, missing values)
Attempting to insert a row with
a foreign key value that does not exist in the referenced table
The request body contains null for a column with
a NOT NULL constraint and no default value
How to fix "Error 400: Bad Request" in Supabase
First, check the full error response — Supabase includes detailed error messages with PGRST error codes and descriptions. Look at the code, message, and hint fields in the JSON response.
For PGRST116 (.single() errors): replace .single() with .maybeSingle() when a query might return zero results. Use .single() only when you are certain exactly one row will match.
For PGRST200 (schema cache errors): open the Supabase SQL Editor and run: NOTIFY pgrst, 'reload schema'; This forces PostgREST to refresh its cached view of your database schema. This is necessary after adding tables, columns, or foreign key relationships.
For data type mismatches: compare the data you are sending with the actual table schema in the Supabase dashboard (Table Editor > select table > see column types). Common mismatches include sending a string where an integer is expected, sending an object where a UUID is expected, or omitting required columns.
For foreign key violations: ensure the referenced row exists before inserting. For example, if your posts table has a user_id foreign key, the user must exist in the users table before you can create a post.
For Edge Function 400 errors: check your function's request parsing logic. A common issue is not handling different Content-Type headers or failing to parse the request body correctly.
// .single() fails when no rows matchconst { data, error } = await supabase .from('profiles') .select('*') .eq('username', searchTerm) .single(); // Throws 400 if 0 or 2+ rows match// Wrong column nameconst { error } = await supabase .from('posts') .insert({ titl: 'Hello', author_id: userId }); // 'titl' not 'title'// .maybeSingle() safely handles 0 rowsconst { data, error } = await supabase .from('profiles') .select('*') .eq('username', searchTerm) .maybeSingle(); // Returns null if no matchif (!data) { console.log('No profile found');}// Correct column name matching schemaconst { error } = await supabase .from('posts') .insert({ title: 'Hello', author_id: userId });if (error) { console.error('Insert failed:', error.message, error.hint);}Prevention tips
- Use .maybeSingle() instead of .single() when a query might return zero results — this avoids the PGRST116 error that is the most common 400 in Supabase
- After changing your database schema (adding tables, columns, or foreign keys), run NOTIFY pgrst, 'reload schema' in the SQL editor to refresh the cache
- Always log the full error response including the code, message, details, and hint fields — Supabase provides detailed diagnostic information in 400 responses
- Compare your insert/update data against the actual table schema in the Supabase dashboard to catch column name typos and type mismatches before they hit the API
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I'm getting 'Error 400: Bad Request' from Supabase when inserting data. The error includes a PGRST error code. How do I decode Supabase PostgREST error codes and fix the most common causes?
My Supabase query returns 'Error 400: Bad Request' with this error body: [paste error JSON]. Explain what the PGRST code means and fix my query to match the table schema.
Frequently asked questions
What causes "Error 400: Bad Request" in Supabase?
The most common causes are: using .single() on queries that return 0 or multiple rows (PGRST116), stale schema cache after database changes (PGRST200), sending data that does not match column types or names, and foreign key constraint violations. Check the PGRST error code in the response for specific diagnostics.
What is the difference between .single() and .maybeSingle() in Supabase?
.single() throws a 400 error if the query returns zero or more than one row. .maybeSingle() returns null for zero rows and throws only for multiple rows. Use .maybeSingle() whenever a query might have no results, which is the safer default.
How do I refresh the PostgREST schema cache in Supabase?
Run this SQL command in the Supabase SQL Editor: NOTIFY pgrst, 'reload schema'; This is necessary after adding tables, columns, foreign keys, or views. Without the refresh, PostgREST may return PGRST200 errors for new relationships.
Why does AI-generated code frequently cause Supabase 400 errors?
AI code generators often use .single() by default, reference column names that do not exist in your actual schema, and generate insert statements without checking NOT NULL constraints. Always verify generated Supabase queries against your actual table structure in the dashboard.
Can RapidDev help fix recurring Supabase 400 errors in my application?
Yes. RapidDev can audit your Supabase queries, fix schema mismatches, implement proper error handling, and set up the Supabase MCP (Model Context Protocol) so AI tools have direct access to your live schema, preventing these errors at the source.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your issue.
Book a free consultation