Skip to main content

Error Handling

This guide covers common HTTP status codes, error response formats, and best practices for handling errors across all WAYSCloud services.

Error Response Format

All WAYSCloud APIs return errors in a consistent JSON format:

{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error description",
"details": {
"field": "parameter_name",
"provided": "invalid_value",
"expected": "expected_format"
}
}
}

Fields:

  • code - Machine-readable error code (see below)
  • message - Human-readable error description
  • details - Optional additional context about the error

HTTP Status Codes

400 Bad Request

The request was malformed or contains invalid parameters.

Example:

{
"error": {
"code": "INVALID_PARAMETER",
"message": "Invalid parameter value",
"details": {
"field": "ttl",
"provided": "-100",
"expected": "Positive integer (60-86400)"
}
}
}

Common Causes:

  • Missing required parameters
  • Invalid parameter format
  • Parameter value out of range
  • Malformed JSON

Resolution:

  • Validate all parameters before sending
  • Check API documentation for required fields
  • Ensure JSON is properly formatted

401 Unauthorized

The API key is missing, invalid, or expired.

Example:

{
"error": {
"code": "AUTH_FAILED",
"message": "Invalid or expired API key"
}
}

Common Causes:

  • Missing Authorization header
  • Invalid API key format
  • API key has been revoked
  • Missing Bearer prefix
  • Extra spaces in header

Resolution:

# Correct format
Authorization: Bearer wayscloud_storage_abc123_YourSecretKey

# Common mistakes:
# ❌ Authorization: wayscloud_storage_abc123_YourSecretKey
# ❌ Authorization: Bearer wayscloud_storage_abc123_YourSecretKey (extra spaces)
# ❌ Authorization: bearer wayscloud_storage_abc123_YourSecretKey (lowercase)

403 Forbidden

The API key doesn't have permission for the requested operation.

Example:

{
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"message": "API key does not have permission for this service"
}
}

Common Causes:

  • Using wrong service key (e.g., storage key for LLM API)
  • Key doesn't have required scope
  • IP not whitelisted (if IP restrictions enabled)

Resolution:

  • Create new API key with correct service permissions
  • Check IP whitelist configuration
  • Verify key scopes in dashboard

404 Not Found

The requested resource doesn't exist.

Example:

{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "The requested resource was not found",
"details": {
"resource_type": "zone",
"resource_id": "zone_xyz123"
}
}
}

Common Causes:

  • Incorrect resource ID
  • Resource has been deleted
  • Wrong endpoint URL
  • Typo in resource name

Resolution:

  • Verify resource exists using list/get operations
  • Check for typos in IDs and URLs
  • Ensure resource wasn't deleted

409 Conflict

The request conflicts with the current state of the resource.

Example:

{
"error": {
"code": "RESOURCE_ALREADY_EXISTS",
"message": "A resource with this name already exists",
"details": {
"resource_type": "database",
"name": "my_app_db"
}
}
}

Common Causes:

  • Duplicate resource name
  • Resource already in desired state
  • Concurrent modification

Resolution:

  • Use unique names for resources
  • Check if resource already exists before creating
  • Implement idempotent operations where possible

413 Request Entity Too Large

The request payload exceeds maximum allowed size.

Example:

{
"error": {
"code": "PAYLOAD_TOO_LARGE",
"message": "Request payload exceeds maximum allowed size",
"details": {
"max_size": "50GB",
"provided_size": "75GB"
}
}
}

Service Limits:

  • Storage: 50GB per file
  • LLM: 32K-200K tokens depending on model
  • Database: 1TB per database

Resolution:

  • Split large uploads using multipart upload (Storage)
  • Reduce context size (LLM)
  • Use chunked uploads for large files

429 Too Many Requests

Rate limit exceeded for your API key.

Example:

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"retry_after": 60,
"details": {
"limit": "1000 requests/minute",
"current_usage": 1000
}
}
}

Resolution:

  • Implement exponential backoff
  • Check Retry-After header
  • Spread requests over time
  • Consider upgrading plan for higher limits

See Rate Limits for detailed limits per service.

500 Internal Server Error

An unexpected error occurred on the server.

Example:

{
"error": {
"code": "INTERNAL_ERROR",
"message": "An internal server error occurred",
"request_id": "req_abc123xyz"
}
}

Resolution:

503 Service Unavailable

The service is temporarily unavailable (maintenance or overload).

Example:

{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Service temporarily unavailable",
"retry_after": 300
}
}

Resolution:

  • Wait and retry after retry_after seconds
  • Check status page for scheduled maintenance
  • Implement retry logic with exponential backoff

507 Insufficient Storage

Storage quota exceeded (Storage API only).

Example:

{
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Storage quota exceeded",
"details": {
"quota": "100GB",
"used": "100GB"
}
}
}

Resolution:

  • Delete unused files
  • Upgrade storage plan
  • Check usage in dashboard

Service-Specific Error Codes

Storage API

CodeDescriptionResolution
BUCKET_NOT_FOUNDBucket doesn't existVerify bucket name
OBJECT_NOT_FOUNDObject doesn't existCheck object key
BUCKET_ALREADY_EXISTSBucket name takenUse different name
INVALID_BUCKET_NAMEInvalid bucket name formatUse lowercase, numbers, hyphens only

LLM API

CodeDescriptionResolution
MODEL_NOT_FOUNDInvalid model nameCheck available models
CONTEXT_LENGTH_EXCEEDEDInput too long for modelReduce input size or use model with larger context
INVALID_MESSAGESMessages format invalidFollow OpenAI message format

Database API

CodeDescriptionResolution
DATABASE_NOT_FOUNDDatabase doesn't existVerify database name
DATABASE_ALREADY_EXISTSDatabase name takenUse different name
SNAPSHOT_NOT_FOUNDSnapshot doesn't existCheck snapshot ID
INVALID_DB_NAMEInvalid database nameUse alphanumeric and underscores only

DNS API

CodeDescriptionResolution
ZONE_NOT_FOUNDZone doesn't existVerify zone ID
RECORD_NOT_FOUNDRecord doesn't existCheck record ID
INVALID_RECORD_TYPEUnsupported record typeUse A, AAAA, CNAME, MX, TXT, SRV, CAA
INVALID_VALUERecord value format invalidCheck value format for record type
DUPLICATE_RECORDRecord already existsUpdate existing record
DNSSEC_ERRORDNSSEC validation failedCheck DS records at registrar

GPU API

CodeDescriptionResolution
JOB_NOT_FOUNDJob doesn't existVerify job ID
INVALID_JOB_TYPEUnsupported job typeUse video_generation, tts, or transcription
CONTENT_MODERATION_FAILEDContent violates policyReview content policy
INSUFFICIENT_CREDITSNot enough creditsAdd credits to account

Retry Strategies

Exponential Backoff

Implement exponential backoff for transient errors (429, 500, 503):

import time
import requests

def api_call_with_retry(url, headers, max_retries=5):
for attempt in range(max_retries):
try:
response = requests.get(url, headers=headers)

if response.status_code == 200:
return response.json()

# Retry on transient errors
if response.status_code in [429, 500, 503]:
retry_after = int(response.headers.get('Retry-After', 2 ** attempt))
print(f"Retry after {retry_after}s (attempt {attempt + 1}/{max_retries})")
time.sleep(retry_after)
continue

# Don't retry on client errors
if 400 <= response.status_code < 500:
response.raise_for_status()

except requests.exceptions.RequestException as e:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)

raise Exception("Max retries exceeded")

JavaScript/Node.js Example

async function apiCallWithRetry(url, headers, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, { headers });

if (response.ok) {
return await response.json();
}

// Retry on transient errors
if ([429, 500, 503].includes(response.status)) {
const retryAfter = parseInt(response.headers.get('Retry-After') || Math.pow(2, attempt));
console.log(`Retry after ${retryAfter}s (attempt ${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}

// Don't retry client errors
if (response.status >= 400 && response.status < 500) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}

} catch (error) {
if (attempt === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}

throw new Error('Max retries exceeded');
}

Best Practices

1. Always Handle Errors

# Bad - no error handling
response = requests.get(url, headers=headers)
data = response.json()

# Good - proper error handling
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
except requests.exceptions.HTTPError as e:
print(f"HTTP error: {e.response.status_code}")
print(f"Error details: {e.response.json()}")
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")

2. Log Request IDs

Always log the request_id from error responses for debugging:

try:
response = requests.post(url, json=data, headers=headers)
response.raise_for_status()
except requests.exceptions.HTTPError as e:
error_data = e.response.json()
request_id = error_data.get('request_id', 'N/A')
print(f"Error: {error_data['error']['message']}")
print(f"Request ID: {request_id}") # Include this when contacting support

3. Validate Before Sending

Validate parameters before making API calls:

def create_dns_record(zone_id, record_type, name, value, ttl):
# Validate parameters
if record_type not in ['A', 'AAAA', 'CNAME', 'MX', 'TXT']:
raise ValueError(f"Invalid record type: {record_type}")

if not (60 <= ttl <= 86400):
raise ValueError(f"TTL must be between 60 and 86400, got {ttl}")

# Make API call
return api_client.create_record(zone_id, record_type, name, value, ttl)

4. Use Timeouts

Always set reasonable timeouts:

# Bad - no timeout (can hang forever)
response = requests.get(url, headers=headers)

# Good - with timeout
response = requests.get(url, headers=headers, timeout=30)

5. Monitor Error Rates

Track error rates in your application:

import logging
from collections import Counter

error_counter = Counter()

def make_api_call(url, headers):
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
status = e.response.status_code
error_counter[status] += 1

# Alert if error rate is high
if error_counter[status] > 100:
logging.error(f"High error rate for status {status}: {error_counter[status]} errors")

raise

Getting Help

If you encounter persistent errors:

  1. Check the error code - See if it's documented above
  2. Review your request - Validate parameters and format
  3. Check service status - https://status.wayscloud.services
  4. Contact support - Include:
    • Error code and message
    • Request ID (if provided)
    • Timestamp of error
    • Endpoint and parameters used (sanitize sensitive data)

Support Channels:

Next Steps