Skip to content

Error Handling

Understand API error responses and how to handle them gracefully.

Error Format

When an API request fails, Nur returns a consistent JSON error response with an appropriate HTTP status code. Every error response includes a code and a human-readable message. Some errors also include a details object with additional context.

1{
2 "error": {
3 "code": "invalid_parameter",
4 "message": "The 'voice_id' parameter is not a valid voice identifier.",
5 "details": {
6 "parameter": "voice_id",
7 "value": "invalid_id_123",
8 "expected": "A valid voice ID starting with 'v_' or a preset voice name"
9 }
10 }
11}

HTTP Status Codes

The API uses standard HTTP status codes to indicate the outcome of a request. Codes in the 4xx range indicate client errors, while 5xx codes indicate server-side issues.

StatusNameDescriptionCommon Causes
400Bad RequestThe request body or parameters are malformed.Invalid JSON, missing required fields, wrong data types
401UnauthorizedAuthentication is missing or invalid.Missing API key, expired key, malformed Authorization header
403ForbiddenThe API key lacks required permissions.Insufficient key scopes, accessing another account's resources
404Not FoundThe requested resource does not exist.Invalid voice ID, deleted resource, wrong endpoint URL
409ConflictThe request conflicts with current state.Duplicate resource creation, concurrent modification
413Payload Too LargeThe request body exceeds the size limit.Audio file too large, text input exceeds character limit
422Unprocessable EntityThe request is well-formed but semantically invalid.Unsupported audio format, invalid language code, incompatible options
429Rate LimitedToo many requests in a given time window.Exceeded per-minute request limit, exceeded monthly quota
500Server ErrorAn unexpected error occurred on the server.Internal bug, infrastructure failure, temporary outage
503Service UnavailableThe service is temporarily unavailable.Planned maintenance, capacity limits, dependency outage

Error Codes

In addition to HTTP status codes, each error response includes a specific error.code string that you can use for programmatic error handling.

CodeHTTP StatusDescription
invalid_api_key401The provided API key is invalid, expired, or has been revoked.
missing_parameter400A required parameter is missing from the request.
invalid_parameter400A parameter value is invalid or out of the accepted range.
file_too_large413The uploaded file exceeds the maximum allowed size.
unsupported_format422The provided file format is not supported for this operation.
voice_not_found404The specified voice ID does not exist or is not accessible.
rate_limit_exceeded429The request rate limit or monthly quota has been exceeded.
insufficient_credits403Your account does not have enough credits for this operation.
service_unavailable503The service is temporarily unavailable. Retry after a short delay.

Handling Errors

The Nur SDKs throw typed error classes that you can catch and handle based on the error type. Always wrap API calls in error handling to provide a graceful experience.

1from nur import NurClient, NurError, RateLimitError
2from nur import ValidationError, AuthenticationError, NotFoundError
3
4client = NurClient()
5
6try:
7 audio = client.tts.generate(
8 text="Hello world",
9 voice_id="rachel_v2",
10 )
11 audio.save("output.mp3")
12
13except AuthenticationError as e:
14 # 401 - Invalid or missing API key
15 print(f"Auth failed: {e.message}")
16
17except NotFoundError as e:
18 # 404 - Resource not found
19 print(f"Not found: {e.message}")
20
21except ValidationError as e:
22 # 400/422 - Invalid parameters
23 print(f"Validation error: {e.message}")
24 if e.details:
25 print(f"Parameter: {e.details.get('parameter')}")
26
27except RateLimitError as e:
28 # 429 - Rate limited
29 print(f"Rate limited. Retry after {e.retry_after}s")
30
31except NurError as e:
32 # Catch-all for any other API error
33 print(f"API error {e.status_code}: {e.code} - {e.message}")

Retry Strategy

Not all errors should be retried. Understanding which errors are transient helps you build a robust integration.

Retryable Errors

  • 429 Rate Limited - retry after the Retry-After delay
  • 500 Server Error - retry with exponential backoff
  • 503 Service Unavailable - retry with exponential backoff

Non-Retryable Errors

  • 400 Bad Request - fix the request parameters
  • 401 Unauthorized - check your API key
  • 403 Forbidden - check key scopes or credits
  • 404 Not Found - verify the resource exists
1import time
2from nur import NurClient, NurError, RateLimitError
3
4client = NurClient()
5
6def call_with_retry(fn, max_retries=5):
7 """Call a function with exponential backoff on retryable errors."""
8 for attempt in range(max_retries):
9 try:
10 return fn()
11
12 except RateLimitError as e:
13 # Use the server-provided Retry-After value
14 wait = e.retry_after or (2 ** attempt)
15 print(f"Rate limited. Waiting {wait}s...")
16 time.sleep(wait)
17
18 except NurError as e:
19 if e.status_code in (500, 503):
20 wait = min(2 ** attempt, 60)
21 print(f"Server error {e.status_code}. Retrying in {wait}s...")
22 time.sleep(wait)
23 else:
24 raise # Non-retryable error
25
26 raise Exception("Max retries exceeded")
27
28# Usage
29audio = call_with_retry(
30 lambda: client.tts.generate(text="Hello", voice_id="rachel_v2")
31)

Rate Limit Headers

Every API response includes rate limit headers so you can proactively manage your request rate before hitting the limit.

1X-RateLimit-Limit: 1000 # Max requests per minute for your tier
2X-RateLimit-Remaining: 847 # Requests remaining in current window
3X-RateLimit-Reset: 1706108400 # Unix timestamp when the window resets
4Retry-After: 12 # Seconds to wait (only on 429 responses)

Tip: Proactive Rate Limiting

Monitor the X-RateLimit-Remaining header and slow down your requests when approaching zero. This is more efficient than waiting for a 429 response and retrying.