Supabase Auth returns the "bad_json" error when the HTTP request body sent to authentication endpoints contains malformed JSON or cannot be parsed. This error prevents authentication operations like sign-up, sign-in, or token refresh and requires fixing the JSON payload structure before retrying.
The "bad_json" error is a Supabase Auth error code that occurs when the authentication API receives an HTTP request with a body that cannot be parsed as valid JSON. Supabase's authentication endpoints (like /auth/v1/signup, /auth/v1/token, etc.) expect properly formatted JSON payloads according to RFC 8259 standards. When the JSON contains syntax errors, malformed structure, encoding issues, or violates basic JSON formatting rules, the API rejects the request with this error before any authentication logic is executed. This is a client-side error that indicates the request payload needs correction.
Use a JSON validator to check for syntax errors before sending to Supabase. Common issues include trailing commas, missing quotes, and unescaped control characters.
# Validate JSON with jq
echo '{"email": "[email protected]", "password": "secret",}' | jq empty
# Or use Python's json.tool
python3 -m json.tool <<< '{"email": "[email protected]", "password": "secret"}'
# Online validators like jsonlint.comFix common JSON issues:
- Remove trailing commas after last item in objects/arrays
- Ensure all property names are quoted with double quotes
- Escape special characters within strings (\", \\, \n, etc.)
- Check for missing braces or brackets
Supabase Auth endpoints require the Content-Type header to be set to "application/json". Without this header, the API may interpret the body differently.
// Correct headers for fetch API
const response = await fetch('https://your-project.supabase.co/auth/v1/signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': 'YOUR_ANON_KEY'
},
body: JSON.stringify({
email: '[email protected]',
password: 'secure-password'
})
});
// Using curl
curl -X POST https://your-project.supabase.co/auth/v1/signup \
-H "Content-Type: application/json" \
-H "apikey: YOUR_ANON_KEY" \
-d '{"email": "[email protected]", "password": "secure-password"}'Note: The Supabase client library automatically sets this header correctly.
The Supabase JavaScript/TypeScript client handles JSON serialization automatically and reduces syntax errors:
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.auth.signUp({
email: '[email protected]',
password: 'secure-password'
});
if (error) {
console.error('Auth error:', error.message);
// Error will be more descriptive than "bad_json"
}
// Other auth methods that handle JSON correctly
const { data: signInData, error: signInError } = await supabase.auth.signInWithPassword({
email: '[email protected]',
password: 'secure-password'
});
const { data: sessionData, error: sessionError } = await supabase.auth.getSession();The client library:
- Automatically sets Content-Type: application/json
- Handles JSON.stringify() for you
- Provides better error messages for validation issues
Non-UTF8 encoding or special characters can break JSON parsing:
// Bad: BOM (Byte Order Mark) at start - common in files saved with BOM
const badJson = '{"email": "[email protected]"}';
// Bad: Unescaped quotes within strings
const badJson2 = '{"message": "He said "hello""}';
// Good: Properly escaped quotes
const goodJson = '{"message": "He said \"hello\""}';
// Check for BOM
function hasBOM(str) {
return str.charCodeAt(0) === 0xFEFF;
}
// Remove BOM if present
function removeBOM(str) {
if (str.charCodeAt(0) === 0xFEFF) {
return str.slice(1);
}
return str;
}Solutions:
- Ensure your JSON is UTF-8 encoded without BOM
- Escape special characters properly (\", \\, \/, \b, \f, \n, \r, \t)
- Validate strings for control characters
Create the simplest possible JSON that should work, then gradually add complexity:
# Start with minimal valid JSON for signup
curl -X POST https://your-project.supabase.co/auth/v1/signup \
-H "Content-Type: application/json" \
-H "apikey: YOUR_ANON_KEY" \
-d '{}' # This will fail with different error (missing fields)
# Add required fields one at a time
curl -X POST https://your-project.supabase.co/auth/v1/signup \
-H "Content-Type: application/json" \
-H "apikey: YOUR_ANON_KEY" \
-d '{"email": "[email protected]"}'
curl -X POST https://your-project.supabase.co/auth/v1/signup \
-H "Content-Type: application/json" \
-H "apikey: YOUR_ANON_KEY" \
-d '{"email": "[email protected]", "password": "secret"}'
# Test other endpoints
curl -X POST https://your-project.supabase.co/auth/v1/token \
-H "Content-Type: application/json" \
-H "apikey: YOUR_ANON_KEY" \
-d '{"email": "[email protected]", "password": "secret", "grant_type": "password"}'This helps identify if the error is specific to certain fields or the entire JSON structure.
Network middleware, proxies, or API gateways might modify your JSON payload:
// Common middleware issues:
// 1. Body parsers that convert JSON to other formats
// 2. Compression middleware that corrupts payload
// 3. Security scanners that modify requests
// 4. Proxy servers that change encoding
// Debug by logging the exact request being sent
console.log('Request body:', JSON.stringify(payload));
console.log('Request headers:', headers);
// Compare what you send vs what Supabase receives
// Enable network logging in browser DevTools or use tools like:
// - Wireshark for packet inspection
// - Charles Proxy for HTTP debugging
// - Browser Network tab for web apps
// If using a proxy, check its configuration:
// - Ensure it preserves Content-Type: application/json
// - Verify it doesn't modify the request body
// - Check for request/response transformationsTemporarily bypass middleware to test if the issue is in your application code or infrastructure.
The "bad_json" error is part of Supabase Auth's error code system, which provides machine-readable error codes for programmatic handling. Unlike generic HTTP 400 errors, "bad_json" specifically indicates JSON parsing failures. This error occurs before any authentication logic runs, so it's not related to credentials, permissions, or user status.
When debugging:
1. Compare your JSON against RFC 8259 standards
2. Remember that JSON requires double quotes for property names (not single quotes)
3. Supabase uses PostgreSQL's JSONB parsing internally, which is strict about syntax
4. Edge cases: very large JSON payloads might hit size limits, but that returns different errors
If you consistently get "bad_json" errors despite valid JSON, check:
- API endpoint URL correctness
- Network timeouts or interruptions during transmission
- Firewall/proxy interference
- Supabase service status (status.supabase.com)
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