API Error Codes and Handling
Complete reference for VocaFuse API error codes and troubleshooting. Explains HTTP status codes, error response formats, and common scenarios. Includes error handling examples in JavaScript and Python.
Error Response Format
All API errors follow a consistent format:
{
"error": {
"code": 2003,
"message": "Invalid field value",
"details": {
"field": "recording_id",
"reason": "must be a valid UUID"
}
}
}
HTTP Status Codes
| Status | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 204 | No Content (successful deletion) |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid API credentials |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource doesn't exist |
| 429 | Rate Limit Exceeded |
| 500 | Internal Server Error |
| 503 | Service Unavailable |
Error Codes
Error codes are organized by category (1xxx = Authentication, 2xxx = Validation, etc.)
Authentication Errors (1xxx)
INVALID_TOKEN (1001)
JWT token is missing or malformed.
{
"error": {
"code": 1001,
"message": "Invalid or malformed token"
}
}
Solution: Ensure you're passing a valid JWT token from your backend
TOKEN_EXPIRED (1002)
JWT token has expired.
{
"error": {
"code": 1002,
"message": "Token has expired"
}
}
Solution: Request a new token from your backend token endpoint
Validation Errors (2xxx)
INVALID_REQUEST_FORMAT (2001)
Request body is malformed or not valid JSON.
{
"error": {
"code": 2001,
"message": "Request body is malformed"
}
}
Solution: Verify your request body is valid JSON
MISSING_REQUIRED_FIELD (2002)
Required field is missing from the request.
{
"error": {
"code": 2002,
"message": "Required field missing",
"details": {
"field": "identity"
}
}
}
Solution: Check API documentation for required fields
INVALID_FIELD_VALUE (2003)
Field value is invalid.
{
"error": {
"code": 2003,
"message": "Invalid field value",
"details": {
"field": "expires_in",
"value": "invalid",
"reason": "must be an integer between 60 and 86400"
}
}
}
Solution: Verify parameter values match the API specification
FILE_SIZE_EXCEEDED (2004)
Uploaded file exceeds size limit.
{
"error": {
"code": 2004,
"message": "File size exceeds maximum limit",
"details": {
"max_size": "25MB",
"actual_size": "30MB"
}
}
}
Solution: Ensure audio files are under 25MB
UNSUPPORTED_AUDIO_FORMAT (2005)
Audio format is not supported.
{
"error": {
"code": 2005,
"message": "Audio format not supported",
"details": {
"format": "mp3",
"supported_formats": ["webm", "wav", "ogg"]
}
}
}
Solution: Convert audio to a supported format (webm, wav, or ogg)
RECORDING_TOO_LONG (2006)
Voice note exceeds maximum duration.
{
"error": {
"code": 2006,
"message": "Recording exceeds maximum duration",
"details": {
"max_duration": 60,
"actual_duration": 75
}
}
}
Solution: Keep voice notes under 60 seconds
Processing Errors (3xxx)
TRANSCRIPTION_FAILED (3003)
Audio transcription failed.
{
"error": {
"code": 3003,
"message": "Failed to transcribe audio",
"details": {
"reason": "Audio quality too low"
}
}
}
Solution: Ensure audio quality is sufficient. Try recording in a quieter environment.
AUDIO_PROCESSING_FAILED (3004)
Audio processing failed.
{
"error": {
"code": 3004,
"message": "Failed to process audio file"
}
}
Solution: Verify the audio file is valid and not corrupted
Rate Limiting (4xxx)
RATE_LIMIT_EXCEEDED (4003)
Too many requests in a given time window.
{
"error": {
"code": 4003,
"message": "Rate limit exceeded",
"details": {
"limit": 100,
"window": "1 minute",
"retry_after": 45
}
}
}
Solution: Implement exponential backoff and retry after the specified time
System Errors (5xxx)
WEBHOOK_ALREADY_EXISTS (5005)
Webhook URL already registered.
{
"error": {
"code": 5005,
"message": "Webhook already exists for this URL",
"details": {
"url": "https://example.com/webhook"
}
}
}
Solution: Use the existing webhook or delete it first before recreating
INTERNAL_SERVER_ERROR (5001)
An unexpected error occurred on the server.
{
"error": {
"code": 5001,
"message": "Internal server error"
}
}
Solution: Retry the request. If the error persists, contact support.
SERVICE_UNAVAILABLE (5002)
Service is temporarily unavailable.
{
"error": {
"code": 5002,
"message": "Service temporarily unavailable"
}
}
Solution: Retry the request after a short delay
Resource Errors (6xxx)
RECORDING_NOT_FOUND (6001)
Voice note doesn't exist or you don't have access.
{
"error": {
"code": 6001,
"message": "Voice note not found",
"details": {
"recording_id": "rec_invalid123"
}
}
}
Solution: Verify the voice note ID is correct
TRANSCRIPTION_NOT_FOUND (6002)
Transcription not available for this voice note.
{
"error": {
"code": 6002,
"message": "Transcription not found",
"details": {
"recording_id": "rec_123"
}
}
}
Solution: Wait for transcription to complete or check if it failed
WEBHOOK_NOT_FOUND (6003)
Webhook doesn't exist.
{
"error": {
"code": 6003,
"message": "Webhook not found",
"details": {
"webhook_id": "webhook_123"
}
}
}
Solution: Verify the webhook ID is correct
Client-Side Errors
Frontend SDK Error Codes
- JavaScript
sdk.addVoiceNote('#record-btn', {
onError: (error) => {
switch (error.code) {
case 'PERMISSION_DENIED':
// User denied microphone access
showMessage('Please allow microphone access');
break;
case 'NOT_SUPPORTED':
// Browser doesn't support recording
showMessage('Browser not supported');
break;
case 'DURATION_EXCEEDED':
// Recording exceeded max duration
showMessage('Recording too long (max 60s)');
break;
case 'NETWORK_ERROR':
// Upload failed due to network
showMessage('Network error. Please try again');
break;
case 'AUTHENTICATION_FAILED':
// Token expired or invalid
await refreshToken();
break;
default:
showMessage(error.userMessage);
}
}
});
Error Object
- TypeScript
interface VocaFuseError {
code: string; // Error code
message: string; // Technical message
userMessage: string; // User-friendly message
details?: object; // Additional context
timestamp: number; // Unix timestamp
}
Error Handling Examples
Python SDK
- Python
- Node.js
from vocafuse import (
Client,
VocaFuseError,
AuthenticationError,
RateLimitError,
NotFoundError
)
client = Client(api_key='sk_live_...', api_secret='...')
try:
recording = client.recordings.get('rec_123')
except AuthenticationError as e:
print(f'Authentication failed: {e.message}')
# Error code 1001 or 1002
# Update credentials or refresh token
except NotFoundError as e:
print(f'Voice note not found: {e.message}')
# Error code 6001
# Handle missing resource
except RateLimitError as e:
retry_after = e.retry_after
print(f'Rate limited. Retry after {retry_after}s')
# Error code 4003
# Implement backoff
time.sleep(retry_after)
except VocaFuseError as e:
print(f'API Error {e.code}: {e.message}')
# Log and handle generic errors
except Exception as e:
print(f'Unexpected error: {e}')
# Handle unexpected errors
import {
Client,
VocaFuseError,
RecordingNotFoundError,
AuthenticationError,
RateLimitError,
} from 'vocafuse-node';
const client = new Client({
apiKey: process.env.VOCAFUSE_API_KEY,
apiSecret: process.env.VOCAFUSE_API_SECRET,
});
async function getRecording(id) {
try {
const recording = await client.recordings(id).get();
console.log('Recording:', recording.data);
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Authentication failed:', error.friendlyMessage);
// Update credentials or refresh token
} else if (error instanceof RateLimitError) {
if (error.retryAfter) {
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));
}
} else if (error instanceof RecordingNotFoundError) {
console.error('Recording not found:', error.friendlyMessage);
// Handle missing resource
} else if (error instanceof VocaFuseError) {
console.error('API error:', error.friendlyMessage);
// Log and handle generic errors
} else {
console.error('Unexpected error:', error);
}
}
}
Retry Logic
- Python
import time
from vocafuse import Client, RateLimitError
def get_recording_with_retry(recording_id, max_retries=3):
client = Client(api_key='sk_live_...', api_secret='...')
for attempt in range(max_retries):
try:
return client.recordings.get(recording_id)
except RateLimitError as e:
# Error code 4003
if attempt < max_retries - 1:
wait_time = e.retry_after
print(f'Rate limited. Waiting {wait_time}s...')
time.sleep(wait_time)
else:
raise
except Exception as e:
if attempt < max_retries - 1:
wait_time = 2 ** attempt # Exponential backoff
print(f'Error: {e}. Retrying in {wait_time}s...')
time.sleep(wait_time)
else:
raise
Best Practices
1. Always Handle Errors
- JavaScript
// ❌ Bad - no error handling
const recording = await client.recordings.get('rec_123');
// ✅ Good - proper error handling
try {
const recording = await client.recordings.get('rec_123');
} catch (error) {
logger.error('Failed to fetch voice note', {
error,
errorCode: error.code,
recordingId: 'rec_123'
});
throw error;
}
2. Implement Retries
- Python
# For transient errors (network, rate limits)
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=60)
)
def create_recording(audio_file):
return client.recordings.create(audio_file)
3. User-Friendly Messages
- JavaScript
function getErrorMessage(error) {
const messages = {
'PERMISSION_DENIED': 'Please allow microphone access to record',
'DURATION_EXCEEDED': 'Recording is too long. Maximum is 60 seconds',
'NETWORK_ERROR': 'Connection lost. Please check your internet',
'AUTHENTICATION_FAILED': 'Session expired. Please refresh the page'
};
return messages[error.code] || 'An error occurred. Please try again';
}
4. Log Errors
- Python
import logging
logger = logging.getLogger(__name__)
try:
recording = client.recordings.get('rec_123')
except VocaFuseError as e:
logger.error(
'API error',
extra={
'error_code': e.code,
'error_message': e.message,
'recording_id': 'rec_123',
'user_id': user.id
}
)
Testing Error Handling
- Python
import pytest
from vocafuse import Client, NotFoundError, RateLimitError
from unittest.mock import patch
def test_handles_not_found():
client = Client(api_key='sk_test_...', api_secret='...')
with pytest.raises(NotFoundError) as exc_info:
client.recordings.get('invalid_id')
assert exc_info.value.code == 6001
def test_retry_on_rate_limit():
client = Client(api_key='sk_test_...', api_secret='...')
# Use mock to simulate rate limit
with patch.object(client.recordings, 'list') as mock:
mock.side_effect = [
RateLimitError(code=4003, retry_after=1),
{'data': []}
]
result = get_recording_with_retry('rec_123')
assert mock.call_count == 2
assert result is not None