Quick Fix
Validate your JSON syntax, ensure all required fields are present, and check that data types match the API schema. Use a JSON validator and refer to the official API documentation.
Common Format Errors
Request format requirements are documented in OpenAI's API reference,Anthropic's API docs, and provider-specific documentation.
JSON Syntax Errors
"Expecting property name enclosed in double quotes"
Malformed JSON structure
Missing Required Fields
"Missing required parameter: 'model'"
Required fields not provided
Type Mismatch
"Invalid type for 'temperature': expected number"
Wrong data type for field
Invalid Values
"temperature must be between 0 and 2"
Values outside allowed range
Correct Request Schemas
Each provider has specific schema requirements. Always refer to the latest documentation for accurate schemas.
OpenAI Chat Completion Schema
interface OpenAIChatRequest {
model: string; // Required: "gpt-4", "gpt-3.5-turbo", etc.
messages: Array<{ // Required: Array of message objects
role: "system" | "user" | "assistant" | "function";
content: string;
name?: string; // Optional: For function messages
function_call?: { // Optional: For function calling
name: string;
arguments: string;
};
}>;
// Optional parameters
temperature?: number; // 0-2, default 1
top_p?: number; // 0-1, default 1
n?: number; // Number of completions
stream?: boolean; // Stream response
stop?: string | string[]; // Stop sequences
max_tokens?: number; // Max response length
presence_penalty?: number; // -2 to 2
frequency_penalty?: number; // -2 to 2
logit_bias?: Record<string, number>;
user?: string; // Unique user identifier
// Function calling
functions?: Array<{
name: string;
description?: string;
parameters: object; // JSON Schema
}>;
function_call?: "none" | "auto" | { name: string };
// JSON mode
response_format?: {
type: "text" | "json_object";
};
}
// Example valid request
const validRequest: OpenAIChatRequest = {
model: "gpt-4",
messages: [
{
role: "system",
content: "You are a helpful assistant."
},
{
role: "user",
content: "Hello, how are you?"
}
],
temperature: 0.7,
max_tokens: 150
};
Anthropic Messages API Schema
interface AnthropicMessageRequest {
model: string; // Required: "claude-3-opus-20240229", etc.
messages: Array<{ // Required: Array of messages
role: "user" | "assistant";
content: string | Array<{ // Can be string or content blocks
type: "text" | "image";
text?: string; // For text blocks
source?: { // For image blocks
type: "base64";
media_type: string;
data: string;
};
}>;
}>;
max_tokens: number; // Required: Maximum tokens to generate
// Optional parameters
system?: string; // System prompt
metadata?: { // User metadata
user_id?: string;
};
stop_sequences?: string[]; // Stop generation at these sequences
temperature?: number; // 0-1, default 1
top_p?: number; // Nucleus sampling
top_k?: number; // Top-k sampling
stream?: boolean; // Stream response
}
// Example valid request
const validAnthropicRequest: AnthropicMessageRequest = {
model: "claude-3-sonnet-20240229",
messages: [
{
role: "user",
content: "What's the weather like?"
}
],
max_tokens: 1000,
system: "You are a weather assistant.",
temperature: 0.5
};
Request Validation Implementation
Implement client-side validation to catch errors before making API calls. Use libraries like Zod orJoi for schema validation.
TypeScript/Zod Validation
import { z } from 'zod';
// Define schemas with Zod
const MessageSchema = z.object({
role: z.enum(['system', 'user', 'assistant', 'function']),
content: z.string().min(1, 'Content cannot be empty'),
name: z.string().optional(),
function_call: z.object({
name: z.string(),
arguments: z.string()
}).optional()
});
const OpenAIRequestSchema = z.object({
model: z.string().min(1, 'Model is required'),
messages: z.array(MessageSchema).min(1, 'At least one message required'),
temperature: z.number().min(0).max(2).optional(),
top_p: z.number().min(0).max(1).optional(),
n: z.number().int().positive().optional(),
stream: z.boolean().optional(),
stop: z.union([z.string(), z.array(z.string())]).optional(),
max_tokens: z.number().int().positive().optional(),
presence_penalty: z.number().min(-2).max(2).optional(),
frequency_penalty: z.number().min(-2).max(2).optional(),
logit_bias: z.record(z.string(), z.number()).optional(),
user: z.string().optional(),
response_format: z.object({
type: z.enum(['text', 'json_object'])
}).optional()
});
// Validation function with detailed errors
export function validateOpenAIRequest(data: unknown): {
valid: boolean;
data?: z.infer<typeof OpenAIRequestSchema>;
errors?: Array<{path: string; message: string}>;
} {
try {
const validated = OpenAIRequestSchema.parse(data);
return { valid: true, data: validated };
} catch (error) {
if (error instanceof z.ZodError) {
const errors = error.errors.map(err => ({
path: err.path.join('.'),
message: err.message
}));
return { valid: false, errors };
}
throw error;
}
}
// Usage with error handling
async function makeOpenAIRequest(requestData: unknown) {
// Validate first
const validation = validateOpenAIRequest(requestData);
if (!validation.valid) {
console.error('Validation errors:', validation.errors);
throw new Error(`Invalid request format: ${
validation.errors?.map(e => `${e.path}: ${e.message}`).join(', ')
}`);
}
// Make API call with validated data
try {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
},
body: JSON.stringify(validation.data)
});
if (!response.ok) {
const error = await response.json();
handleAPIError(error);
}
return await response.json();
} catch (error) {
console.error('API request failed:', error);
throw error;
}
}
// Specific error handling
function handleAPIError(error: any) {
if (error.error?.type === 'invalid_request_error') {
// Log the specific field that caused the error
console.error('Invalid request:', error.error.message);
// Common fixes based on error message
if (error.error.message.includes('model')) {
console.log('Fix: Check if the model name is correct and you have access');
} else if (error.error.message.includes('messages')) {
console.log('Fix: Ensure messages array is properly formatted');
}
}
throw new Error(error.error?.message || 'Unknown API error');
}
Python Request Validation
from typing import Dict, List, Any, Optional, Union
from pydantic import BaseModel, Field, validator
import json
from enum import Enum
class MessageRole(str, Enum):
system = "system"
user = "user"
assistant = "assistant"
function = "function"
class Message(BaseModel):
role: MessageRole
content: str = Field(..., min_length=1)
name: Optional[str] = None
function_call: Optional[Dict[str, Any]] = None
@validator('content')
def content_not_empty(cls, v):
if not v or not v.strip():
raise ValueError('Message content cannot be empty')
return v
class OpenAIRequest(BaseModel):
model: str = Field(..., min_length=1)
messages: List[Message] = Field(..., min_items=1)
temperature: Optional[float] = Field(None, ge=0, le=2)
top_p: Optional[float] = Field(None, ge=0, le=1)
n: Optional[int] = Field(None, gt=0)
stream: Optional[bool] = None
stop: Optional[Union[str, List[str]]] = None
max_tokens: Optional[int] = Field(None, gt=0)
presence_penalty: Optional[float] = Field(None, ge=-2, le=2)
frequency_penalty: Optional[float] = Field(None, ge=-2, le=2)
logit_bias: Optional[Dict[str, float]] = None
user: Optional[str] = None
@validator('messages')
def validate_message_order(cls, messages):
"""Ensure conversation flow makes sense"""
if not messages:
return messages
# First message can be system or user
if messages[0].role not in [MessageRole.system, MessageRole.user]:
raise ValueError('First message must be from system or user')
# Check for alternating pattern (simplified)
for i in range(1, len(messages)):
if messages[i].role == messages[i-1].role == MessageRole.user:
# Allow multiple user messages but warn
print("Warning: Multiple consecutive user messages")
return messages
class Config:
use_enum_values = True
json_encoders = {
Enum: lambda x: x.value
}
class RequestValidator:
"""Validate and fix common request issues"""
@staticmethod
def validate_openai_request(data: Dict[str, Any]) -> Dict[str, Any]:
"""Validate and clean OpenAI request"""
try:
# Parse with Pydantic
request = OpenAIRequest(**data)
# Additional custom validations
if request.model.startswith("gpt-4") and request.max_tokens and request.max_tokens > 8000:
print(f"Warning: max_tokens {request.max_tokens} might be too high for {request.model}")
return request.dict(exclude_none=True)
except ValidationError as e:
# Extract user-friendly error messages
errors = []
for error in e.errors():
field = '.'.join(str(x) for x in error['loc'])
message = error['msg']
errors.append(f"{field}: {message}")
raise ValueError(f"Invalid request format: {'; '.join(errors)}")
@staticmethod
def fix_common_issues(data: Dict[str, Any]) -> Dict[str, Any]:
"""Attempt to fix common formatting issues"""
# Fix common typos in model names
if 'model' in data:
model_fixes = {
'gpt4': 'gpt-4',
'gpt3.5': 'gpt-3.5-turbo',
'claude3': 'claude-3-sonnet-20240229',
'gpt-4-turbo': 'gpt-4-turbo-preview'
}
if data['model'] in model_fixes:
data['model'] = model_fixes[data['model']]
print(f"Fixed model name: {data['model']}")
# Ensure messages is a list
if 'messages' in data and isinstance(data['messages'], dict):
data['messages'] = [data['messages']]
# Fix temperature/top_p conflicts
if data.get('temperature') == 0 and data.get('top_p') is not None:
del data['top_p']
print("Removed top_p when temperature is 0")
# Convert string numbers to actual numbers
for field in ['temperature', 'top_p', 'max_tokens', 'n']:
if field in data and isinstance(data[field], str):
try:
if field in ['temperature', 'top_p']:
data[field] = float(data[field])
else:
data[field] = int(data[field])
except ValueError:
del data[field]
print(f"Removed invalid {field} value")
return data
# Usage example
def make_validated_request(request_data: Dict[str, Any]):
"""Make API request with validation and error handling"""
# First try to fix common issues
request_data = RequestValidator.fix_common_issues(request_data)
# Validate
try:
validated_data = RequestValidator.validate_openai_request(request_data)
except ValueError as e:
print(f"Validation error: {e}")
# Attempt recovery for specific errors
if "messages" in str(e):
# Provide a default message
request_data['messages'] = [{
'role': 'user',
'content': request_data.get('prompt', 'Hello')
}]
validated_data = RequestValidator.validate_openai_request(request_data)
else:
raise
# Make API call
import openai
try:
response = openai.ChatCompletion.create(**validated_data)
return response
except openai.error.InvalidRequestError as e:
# Handle API-level validation errors
error_msg = str(e)
if "maximum context length" in error_msg:
# Reduce message history or max_tokens
print("Reducing request size due to context length")
if 'max_tokens' in validated_data:
validated_data['max_tokens'] = min(validated_data['max_tokens'], 1000)
if len(validated_data['messages']) > 2:
validated_data['messages'] = validated_data['messages'][-2:]
# Retry with reduced request
return openai.ChatCompletion.create(**validated_data)
raise
# Test the validator
test_requests = [
# Valid request
{
"model": "gpt-4",
"messages": [{"role": "user", "content": "Hello"}]
},
# Missing required field
{
"messages": [{"role": "user", "content": "Hello"}]
},
# Invalid temperature
{
"model": "gpt-4",
"messages": [{"role": "user", "content": "Hello"}],
"temperature": 3.0 # Too high
},
# Wrong type
{
"model": "gpt-4",
"messages": "Hello", # Should be array
"temperature": "0.7" # Should be number
}
]
for i, test_data in enumerate(test_requests):
print(f"\nTest {i + 1}:")
try:
validated = RequestValidator.validate_openai_request(test_data.copy())
print("✓ Valid request")
except ValueError as e:
print(f"✗ {e}")
Debugging Request Format Errors
Request Logger and Debugger
class APIRequestDebugger {
private enabled: boolean = process.env.NODE_ENV === 'development';
logRequest(
endpoint: string,
requestData: any,
headers: Record<string, string>
): void {
if (!this.enabled) return;
console.group(`🔍 API Request to ${endpoint}`);
// Log formatted JSON
console.log('📦 Request Body:');
console.log(JSON.stringify(requestData, null, 2));
// Validate JSON syntax
try {
JSON.parse(JSON.stringify(requestData));
console.log('✅ Valid JSON syntax');
} catch (e) {
console.error('❌ Invalid JSON:', e.message);
}
// Check for common issues
this.checkCommonIssues(requestData);
// Log headers (hide sensitive data)
console.log('📋 Headers:');
const safeHeaders = { ...headers };
if (safeHeaders.Authorization) {
safeHeaders.Authorization = safeHeaders.Authorization.substring(0, 20) + '...';
}
console.table(safeHeaders);
console.groupEnd();
}
private checkCommonIssues(data: any): void {
const issues: string[] = [];
// Check for undefined values
const checkUndefined = (obj: any, path: string = ''): void => {
for (const [key, value] of Object.entries(obj)) {
const currentPath = path ? `${path}.${key}` : key;
if (value === undefined) {
issues.push(`Undefined value at ${currentPath}`);
} else if (value === null) {
issues.push(`Null value at ${currentPath} (might be intentional)`);
} else if (typeof value === 'object' && !Array.isArray(value)) {
checkUndefined(value, currentPath);
}
}
};
checkUndefined(data);
// OpenAI specific checks
if (data.messages && Array.isArray(data.messages)) {
data.messages.forEach((msg: any, index: number) => {
if (!msg.role) {
issues.push(`Message at index ${index} missing 'role'`);
}
if (!msg.content && msg.content !== '') {
issues.push(`Message at index ${index} missing 'content'`);
}
});
}
// Type checks
if (data.temperature !== undefined && typeof data.temperature !== 'number') {
issues.push(`'temperature' should be a number, got ${typeof data.temperature}`);
}
if (data.max_tokens !== undefined && !Number.isInteger(data.max_tokens)) {
issues.push(`'max_tokens' should be an integer`);
}
// Log issues
if (issues.length > 0) {
console.warn('⚠️ Potential issues found:');
issues.forEach(issue => console.warn(` - ${issue}`));
} else {
console.log('✅ No obvious issues detected');
}
}
logResponse(response: Response, data: any): void {
if (!this.enabled) return;
console.group(`📨 API Response (Status: ${response.status})`);
if (!response.ok) {
console.error('❌ Request failed');
console.log('Error details:', data);
// Parse error message for hints
if (data.error?.message) {
this.suggestFixes(data.error.message);
}
} else {
console.log('✅ Request successful');
}
console.groupEnd();
}
private suggestFixes(errorMessage: string): void {
console.log('💡 Suggested fixes:');
const fixes: Record<string, string> = {
'model': 'Check model name spelling and availability',
'messages': 'Ensure messages is an array with proper role/content structure',
'required': 'Add the missing required field to your request',
'type': 'Check data types - numbers should not be strings',
'format': 'Validate JSON syntax using a JSON validator',
'Invalid value': 'Check API documentation for allowed values',
'exceeds': 'Reduce the value to be within allowed limits'
};
for (const [keyword, fix] of Object.entries(fixes)) {
if (errorMessage.toLowerCase().includes(keyword.toLowerCase())) {
console.log(` → ${fix}`);
}
}
}
}
// Usage
const debugger = new APIRequestDebugger();
async function makeDebuggedRequest(requestData: any) {
const endpoint = 'https://api.openai.com/v1/chat/completions';
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
};
// Log request
debugger.logRequest(endpoint, requestData, headers);
try {
const response = await fetch(endpoint, {
method: 'POST',
headers,
body: JSON.stringify(requestData)
});
const data = await response.json();
// Log response
debugger.logResponse(response, data);
if (!response.ok) {
throw new Error(data.error?.message || 'Request failed');
}
return data;
} catch (error) {
console.error('Request error:', error);
throw error;
}
}
Common Format Fixes
1. JSON Syntax Issues
❌ Wrong
{
"model": "gpt-4",
"messages": [
{
"role": "user"
"content": "Hello" // Missing comma
}
],
"temperature": 0.7, // Trailing comma
}
✅ Correct
{
"model": "gpt-4",
"messages": [
{
"role": "user",
"content": "Hello"
}
],
"temperature": 0.7
}
2. Type Mismatches
❌ Wrong
{
"temperature": "0.7", // String instead of number
"max_tokens": "100", // String instead of number
"stream": "true", // String instead of boolean
"messages": { // Object instead of array
"role": "user",
"content": "Hello"
}
}
✅ Correct
{
"temperature": 0.7, // Number
"max_tokens": 100, // Number
"stream": true, // Boolean
"messages": [{ // Array
"role": "user",
"content": "Hello"
}]
}
3. Missing Required Fields
❌ Wrong
// OpenAI - Missing model
{
"messages": [{"role": "user", "content": "Hi"}]
}
// Anthropic - Missing max_tokens
{
"model": "claude-3-sonnet-20240229",
"messages": [{"role": "user", "content": "Hi"}]
}
✅ Correct
// OpenAI
{
"model": "gpt-4",
"messages": [{"role": "user", "content": "Hi"}]
}
// Anthropic
{
"model": "claude-3-sonnet-20240229",
"messages": [{"role": "user", "content": "Hi"}],
"max_tokens": 1000
}
API Validation Middleware
// Express middleware for request validation
import { Request, Response, NextFunction } from 'express';
import Ajv from 'ajv';
const ajv = new Ajv({ allErrors: true });
// Define JSON Schema for OpenAI requests
const openAISchema = {
type: 'object',
required: ['model', 'messages'],
properties: {
model: { type: 'string', minLength: 1 },
messages: {
type: 'array',
minItems: 1,
items: {
type: 'object',
required: ['role', 'content'],
properties: {
role: { enum: ['system', 'user', 'assistant', 'function'] },
content: { type: 'string' },
name: { type: 'string' },
function_call: {
type: 'object',
properties: {
name: { type: 'string' },
arguments: { type: 'string' }
}
}
}
}
},
temperature: { type: 'number', minimum: 0, maximum: 2 },
top_p: { type: 'number', minimum: 0, maximum: 1 },
n: { type: 'integer', minimum: 1 },
stream: { type: 'boolean' },
stop: {
oneOf: [
{ type: 'string' },
{ type: 'array', items: { type: 'string' } }
]
},
max_tokens: { type: 'integer', minimum: 1 },
presence_penalty: { type: 'number', minimum: -2, maximum: 2 },
frequency_penalty: { type: 'number', minimum: -2, maximum: 2 }
}
};
const validateOpenAI = ajv.compile(openAISchema);
export const validateRequestMiddleware = (
req: Request,
res: Response,
next: NextFunction
) => {
// Skip validation for non-JSON requests
if (!req.is('application/json')) {
return res.status(415).json({
error: 'Content-Type must be application/json'
});
}
// Validate based on endpoint
const path = req.path;
let validate;
if (path.includes('openai') || path.includes('chat/completions')) {
validate = validateOpenAI;
} else {
// Add other validators as needed
return next();
}
const valid = validate(req.body);
if (!valid) {
// Format validation errors
const errors = validate.errors?.map(err => ({
field: err.instancePath || err.schemaPath,
message: err.message,
params: err.params
}));
return res.status(400).json({
error: 'Invalid request format',
details: errors,
suggestion: getErrorSuggestion(errors?.[0])
});
}
// Add cleaned/validated data to request
req.body = ajv.compile(openAISchema)(req.body);
next();
};
function getErrorSuggestion(error: any): string {
if (!error) return 'Check your request format against the API documentation';
const field = error.field;
const message = error.message;
// Provide specific suggestions
if (field.includes('model')) {
return 'Ensure model name is correct (e.g., "gpt-4", "gpt-3.5-turbo")';
}
if (field.includes('messages')) {
return 'Messages must be an array of {role, content} objects';
}
if (message.includes('required')) {
return `Add the missing required field: ${field}`;
}
if (message.includes('type')) {
return `Check the data type for ${field}`;
}
return message;
}
Best Practices
Do's
- • Validate requests before sending
- • Use schema validation libraries
- • Handle type conversions properly
- • Log request/response for debugging
- • Implement proper error handling
- • Keep schemas up to date
- • Test with various inputs
Don'ts
- • Don't send unvalidated user input
- • Don't ignore validation errors
- • Don't use outdated API schemas
- • Don't mix up data types
- • Don't forget required fields
- • Don't hardcode error messages
- • Don't skip error logging
References
- [1] OpenAI. "Error Codes Reference" (2024)
- [2] Anthropic. "API Errors" (2024)
- [3] Stack Overflow. "OpenAI API Questions" (2024)