Skip to content

Error Handling

TruthVouch uses standard HTTP status codes and structured error responses. All SDKs provide typed exceptions for error handling.

Error Response Format

All errors follow this structure:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request payload",
"statusCode": 400,
"details": [
{
"field": "response",
"message": "response is required"
}
],
"requestId": "req_1234567890abcdef"
}
}

Fields:

  • code — Standardized error code for programmatic handling
  • message — Human-readable description
  • statusCode — HTTP status code
  • details — Field-level errors (validation errors only)
  • requestId — Request ID for support reference

Error Codes

Client Errors (4xx)

CodeHTTPMeaningResolution
INVALID_REQUEST400Malformed request (missing body, invalid JSON)Check request format
VALIDATION_ERROR422Invalid field valuesCheck details array for per-field errors
INVALID_API_KEY401API key missing, invalid, or revokedVerify key in Settings → API Keys
INSUFFICIENT_PERMISSIONS403API key lacks permission for this operationCheck subscription tier
RESOURCE_NOT_FOUND404Resource doesn’t existVerify resource ID
RESOURCE_ALREADY_EXISTS409Duplicate resource creation attemptCheck if resource already exists
RATE_LIMIT_EXCEEDED429Too many requestsWait and retry (see Retry-After header)

Server Errors (5xx)

CodeHTTPMeaningResolution
INTERNAL_ERROR500Unexpected server errorRetry with exponential backoff
SERVICE_UNAVAILABLE503Maintenance or outageCheck status page

Governance Errors

CodeHTTPMeaning
POLICY_BLOCKED403Request blocked by governance policy
PII_DETECTED403PII detected and policy blocks request
INJECTION_ATTEMPT_DETECTED403Prompt injection detected and blocked

Example Errors

Validation Error

Request:

Terminal window
curl -X POST https://api.truthvouch.com/api/v1/governance/scan \
-H "Authorization: Bearer tv_live_..." \
-H "Content-Type: application/json" \
-d '{"prompt": "Tell me..."}' # missing "response"

Response (422):

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"statusCode": 422,
"details": [
{
"field": "response",
"message": "response is required"
}
],
"requestId": "req_abc123"
}
}

Authentication Error

Request:

Terminal window
curl -H "Authorization: Bearer invalid_key" \
https://api.truthvouch.com/api/v1/alerts

Response (401):

{
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid or expired API key",
"statusCode": 401,
"requestId": "req_def456"
}
}

Rate Limit Error

Response (429):

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded: 1000 requests per minute",
"statusCode": 429,
"requestId": "req_ghi789"
}
}

Plus headers:

Retry-After: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1678886460

Policy Blocked Error

Response (403):

{
"error": {
"code": "POLICY_BLOCKED",
"message": "Request blocked by governance policy",
"statusCode": 403,
"requestId": "req_jkl012"
},
"governance": {
"verdict": "blocked",
"policy_id": "policy_123",
"violation_reason": "Suspected hallucination detected"
}
}

Error Handling by SDK

Python

from truthvouch import (
TruthVouchClient,
PolicyBlockedError,
AuthenticationError,
RateLimitError,
TruthVouchError,
)
try:
response = await client.openai.chat.completions.create(...)
except PolicyBlockedError as e:
# Request was blocked by policy
print(f"Blocked: {e.governance_report.policy_id}")
except RateLimitError as e:
# Rate limit exceeded
print(f"Retry after: {e.retry_after}s")
except AuthenticationError as e:
# Invalid API key
print(f"Auth failed: {e}")
except TruthVouchError as e:
# Generic error
print(f"Error: {e}")

TypeScript

import TruthVouch, {
PolicyBlockedError,
AuthenticationError,
RateLimitError,
} from '@truthvouch/sdk';
try {
const response = await tv.openai.chat.completions.create({...});
} catch (error) {
if (error instanceof PolicyBlockedError) {
console.log(`Blocked: ${error.governanceReport.policyId}`);
} else if (error instanceof RateLimitError) {
console.log(`Retry after: ${error.retryAfter}s`);
} else if (error instanceof AuthenticationError) {
console.log(`Auth failed: ${error.message}`);
} else {
console.error(`Error: ${error}`);
}
}

.NET

try
{
var response = await client.Chat.CreateAsync(request, ct);
}
catch (GovernancePolicyViolationException ex)
{
_logger.LogWarning("Blocked by policy: {PolicyId}",
ex.GovernanceReport?.PolicyId);
}
catch (TruthVouchAuthException ex)
{
_logger.LogError("Auth failed: {RequestId}", ex.RequestId);
}
catch (QuotaExceededException ex)
{
_logger.LogWarning("Rate limited, retry after {Seconds}s", ex.RetryAfterSeconds);
}
catch (TruthVouchException ex)
{
_logger.LogError("Error [{Code}]: {Message}", ex.ErrorCode, ex.Message);
}

Retry Strategy

Idempotent Requests

Safe to retry (GET, POST with idempotency key):

  • 429 (Rate Limit) — retry with backoff
  • 500 (Server Error) — retry with backoff
  • 503 (Service Unavailable) — retry with longer backoff

Non-Idempotent Requests

Do not retry without an idempotency key:

  • POST without idempotency key — risk duplicate resources
  • PATCH/PUT — may cause unintended side effects
  • DELETE — may delete multiple times

Use Idempotency-Key header to safely retry:

Terminal window
curl -X POST https://api.truthvouch.com/api/v1/governance/scan \
-H "Authorization: Bearer tv_live_..." \
-H "Idempotency-Key: req_abc123_scan_1" \
-d '{"prompt":"...","response":"..."}'

Same idempotency key in retries ensures the request is processed only once.

Exponential Backoff

Implement backoff for transient errors:

import time
import random
def retry_with_backoff(func, max_retries=5):
for attempt in range(max_retries):
try:
return func()
except (RateLimitError, ConnectionError) as e:
if attempt == max_retries - 1:
raise
wait_time = (2 ** attempt) + random.uniform(0, 1)
print(f"Retry {attempt+1}/{max_retries} after {wait_time:.1f}s")
time.sleep(wait_time)
# SDKs do this automatically with max_retries parameter

Handling Specific Scenarios

401 Unauthorized

Causes:

  • Invalid API key
  • Expired JWT token
  • Key has been revoked

Solutions:

  1. Verify API key is correct
  2. For JWT tokens, refresh using refresh token
  3. Check if key has been deleted in Settings → API Keys
  4. Generate a new API key if needed

403 Forbidden

Causes:

  • Insufficient permissions (subscription tier too low)
  • Governance policy violation
  • Organization doesn’t have access to this feature

Solutions:

  1. Check subscription tier (Settings → Billing)
  2. If policy blocked, review governance policy
  3. Contact support for permission issues

429 Rate Limited

Causes:

  • Exceeded rate limit for your tier

Solutions:

  1. Wait and retry (see Retry-After header)
  2. Reduce request frequency
  3. Use batch APIs for bulk operations
  4. Upgrade to higher tier if persistent

503 Service Unavailable

Causes:

  • Maintenance window
  • Service outage
  • Cloud provider issue

Solutions:

  1. Check status page
  2. Implement exponential backoff retry
  3. Contact support if outage persists >15 minutes

Next Steps