Supabase (PostgREST) returns PGRST102 when the JSON payload sent to a REST endpoint is malformed, contains syntax errors, or violates schema constraints. This error prevents the request from reaching the database and requires fixing the JSON structure before resubmitting.
PostgREST, the REST API layer in front of Supabase's PostgreSQL database, validates every JSON payload before passing it to the database. The "Invalid JSON body" error (PGRST102) occurs when PostgREST cannot parse the JSON due to syntax errors, malformed structure, or when the JSON violates the expected schema for the target table. This validation happens before any database operations, ensuring that only valid data reaches your tables. The error is part of PostgREST's Group 1 API request errors, which handle HTTP semantics and payload validation.
Use a JSON validator to check for syntax errors. Common issues include trailing commas, missing quotes, and unescaped control characters.
# Validate JSON with jq
echo '{"name": "test", "age": 25,}' | jq empty
# Or use Python
python3 -m json.tool <<< '{"name": "test", "age": 25}'If the validator reports errors, fix them before sending to Supabase. Pay special attention to:
- Trailing commas after the last item in objects/arrays
- Missing quotes around property names
- Unescaped quotes within strings
- Invalid control characters
Compare your JSON payload against your Supabase table schema. Ensure data types match (strings vs numbers, booleans vs strings).
-- Check your table schema in Supabase SQL Editor
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'your_table';Common mismatches:
- Sending string "25" for integer column
- Sending boolean true/false as string "true"/"false"
- Sending null for NOT NULL columns
- Exceeding varchar length limits
Different Supabase endpoints expect different JSON structures:
// For inserting a single row - send object
const correctSingle = { name: 'John', age: 30 };
// For inserting multiple rows - send array of objects
const correctMultiple = [
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 }
];
// For upsert - include primary key
const correctUpsert = { id: 1, name: 'John', age: 30 };
// For update - partial object is fine
const correctUpdate = { age: 31 }; // PATCH requestCheck if you're sending an array when the endpoint expects an object, or vice versa.
The Supabase JavaScript/TypeScript client handles JSON serialization automatically and provides better error messages:
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
// Let the client handle JSON serialization
const { data, error } = await supabase
.from('users')
.insert({ name: 'John', age: 30 });
if (error) {
console.error('Detailed error:', error);
// Error will include specific validation details
}The client library also:
- Automatically sets Content-Type header
- Handles JSON.stringify() for you
- Provides TypeScript types for schema validation
Non-UTF8 encoding or special characters can break JSON parsing:
// Bad: BOM (Byte Order Mark) at start
const badJson = '{"name": "test"}';
// Bad: Unescaped quotes
const badJson2 = '{"message": "He said "hello""}';
// Good: Escaped quotes
const goodJson = '{"message": "He said \"hello\""}';
// Check encoding
console.log('First char code:', jsonString.charCodeAt(0));
// If 65279 (0xFEFF), you have a BOMSolutions:
- Ensure your JSON is UTF-8 encoded
- Escape special characters properly
- Remove any BOM from the beginning of files
Create the simplest possible JSON that should work, then gradually add complexity:
// Start with minimal valid JSON
const minimal = {};
// Add one field at a time
const withOneField = { id: 1 };
// Test each field individually
const testFields = [
{ name: 'test' },
{ age: 25 },
{ active: true },
{ tags: ['a', 'b'] }
];
// Use curl for direct testing
curl -X POST https://your-project.supabase.co/rest/v1/table -H "apikey: YOUR_ANON_KEY" -H "Authorization: Bearer YOUR_JWT" -H "Content-Type: application/json" -d '{}' # Start empty, then add fieldsThis helps identify which specific field or structure causes the error.
PostgREST uses PostgreSQL's JSONB type for parsing and validation, which is strict about JSON syntax. The PGRST102 error occurs during the JSON parsing phase before any database constraints are checked. If you're working with large JSON payloads, consider:
1. Using PostgreSQL's JSONB operators for partial updates instead of sending full objects
2. Implementing row-level security policies that might reject certain JSON structures
3. Using database triggers that validate JSON content
4. Setting up JSON schema validation in PostgreSQL if you need strict structural validation
Remember that PostgREST follows RFC 8259 for JSON parsing, so ensure your JSON complies with this standard.
email_conflict_identity_not_deletable: Cannot delete identity because of email conflict
How to fix "Cannot delete identity because of email conflict" in Supabase
mfa_challenge_expired: MFA challenge has expired
How to fix "mfa_challenge_expired: MFA challenge has expired" in Supabase
conflict: Database conflict, usually related to concurrent requests
How to fix "database conflict usually related to concurrent requests" in Supabase
phone_exists: Phone number already exists
How to fix "phone_exists" in Supabase
StorageApiError: resource_already_exists
StorageApiError: Resource already exists