1. Symptoms
The clw-api-exhausted error in OpenClaw manifests during API interactions when the service detects quota overuse. This typically halts computations or data fetches, returning a structured error response.
Common symptoms include:
- API calls failing mid-session with immediate rejection.
- Console or log output showing quota depletion warnings.
- Reduced throughput in batch processing scripts.
- Dashboard alerts in the OpenClaw console indicating “API Exhausted”.
Error: clw-api-exhausted
Message: API quota exhausted for account 'user123'. Daily limit of 10,000 calls reached.
Remaining: 0/10000
Retry after: 2024-10-18T23:59:59Z
HTTP Status: 429 Too Many Requests
In Python SDK usage:
Traceback (most recent call last):
File "compute.py", line 45, in <module>
result = client.run_compute(job_config)
openclaw.exceptions.APIExhaustedError: clw-api-exhausted: Quota exceeded. Upgrade to Pro plan or wait for reset.
Node.js example:
OpenClawError: clw-api-exhausted
at Client.runCompute (/node_modules/openclaw-sdk/index.js:234:15)
{
code: 'clw-api-exhausted',
message: 'API quota exhausted. Calls today: 10001/10000',
retryAfter: 3600
}
Rust crate users see:
Error { kind: ApiExhausted, message: "clw-api-exhausted: Quota limit hit" }
Performance degrades: scripts that previously processed 1,000 jobs/min now stall after 500. Network traces show 429 responses with X-RateLimit-Remaining: 0 headers. This error blocks CI/CD pipelines, data pipelines, and real-time apps relying on OpenClaw’s compute API.
2. Root Cause
OpenClaw enforces strict quotas to manage shared resources:
- Free tier: 10,000 calls/day, 100/minute.
- Pro tier: 100,000 calls/day, 1,000/minute.
- Enterprise: Custom limits.
The clw-api-exhausted triggers when:
- Cumulative calls exceed daily/hourly limits.
- No backoff logic in client code amplifies bursts.
- Parallel workers (e.g., multiprocessing) ignore shared quotas.
- Forgotten polling loops consume quota silently.
- Account-level limits shared across all API keys/apps.
Internally, OpenClaw uses Redis for sliding-window counters. Exceeding increments a ban flag until reset (UTC midnight).
Examine headers in failed responses:
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1729324800
Root causes from traces:
- Tight loops without
time.sleep(). - Unbounded fan-out in async tasks.
- No quota prefetch via
/v1/account/quotaendpoint.
This is not a bug but a deliberate throttle. Ignoring it risks permanent bans.
3. Step-by-Step Fix
Resolve by monitoring quotas, adding retries, batching, and scaling plans.
Step 1: Query Current Quota
Fetch usage before heavy loads.
import openclaw
client = openclaw.Client(api_key="your_key")
quota = client.get_quota()
print(f"Remaining: {quota.remaining_daily}/{quota.limit_daily}")
Step 2: Implement Exponential Backoff Retry
Wrap API calls in a retry decorator handling 429s.
Before:
import openclaw
import time
client = openclaw.Client(api_key="your_key")
for i in range(10000): # Exceeds quota fast
result = client.run_compute({"task": f"job-{i}"})
print(result)
# Fails with clw-api-exhausted after ~5000 calls
After:
import openclaw
import time
from functools import wraps
import random
def backoff_retry(max_attempts=5, base_delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except openclaw.exceptions.APIExhaustedError as e:
if attempt == max_attempts - 1:
raise
delay = (base_delay * 2 ** attempt) + random.uniform(0, 1)
print(f"Quota hit, backing off {delay:.2f}s (attempt {attempt+1})")
time.sleep(delay)
return None
return wrapper
return decorator
client = openclaw.Client(api_key="your_key")
@backoff_retry()
def safe_compute(task):
return client.run_compute({"task": task})
for i in range(10000):
result = safe_compute(f"job-{i}")
if result:
print(result)
time.sleep(0.1) # Rate limit to 10/sec
Step 3: Batch Requests
Use /v1/batch_compute endpoint.
Before:
jobs = [{"task": f"job-{i}"} for i in range(100)]
for job in jobs:
client.run_compute(job) # 100 calls
After:
batch_jobs = [{"task": f"job-{i}"} for i in range(100)]
results = client.batch_compute(batch_jobs) # 1 call
Step 4: Preflight Quota Check
def check_quota_threshold(client, threshold=0.9):
quota = client.get_quota()
if quota.remaining_daily / quota.limit_daily < threshold:
raise ValueError("Quota low, aborting.")
Step 5: Upgrade Plan (if needed)
Via dashboard: Account > Billing > Upgrade to Pro.
Step 6: Use Multiple API Keys
Rotate keys across worker pools.
keys = ["key1", "key2"]
client = openclaw.Client(api_key=keys[i % len(keys)])
4. Verification
Run quota check:
$ python quota_check.py Remaining: 9500/10000 # Green if >20%Stress test with fixed code:
$ python stress_test.py --jobs 5000 All 5000 jobs completed. No clw-api-exhausted.Monitor headers:
curl -H "Authorization: Bearer your_key" https://api.openclaw.io/v1/quota # X-RateLimit-Remaining >0Pipeline run: Deploy to CI, confirm no failures.
Logs: Grep for “backoff” – should see occasional but no crashes.
Success metric: 99% uptime under load, quota utilization <80%.
5. Common Pitfalls
Ignoring Headers: Clients not parsing
Retry-Afterlead to busy loops.# Wrong while True: try: client.call() except: pass # Spins CPUShared Quota Oversight: Multiprocess ignores account limits. Fix: Central quota service with Redis.
Async Overload:
asyncio.gather(1000 tasks)bursts quota. Useasyncio.Semaphore(10).Polling Loops: Status checks every 1s eat quota.
# Bad while not done: status = client.get_status(job_id) time.sleep(1) # Good: Webhooks or 30s intervalsNo Logging: Hard to debug without
loggingquota events.Free Tier Trap: Prototyping scales to prod without upgrade.
UTC Reset Blindness: Local time mismatches cause surprise exhaustions.
⚠️ Unverified: Custom enterprise limits may vary; contact support.
6. Related Errors
| Error Code | Description | Fix Summary |
|---|---|---|
| clw-rate-limit-exceeded | Per-minute burst limit hit | Add fixed delays, semaphores |
| clw-auth-invalid | Bad/missing API key | Regenerate key, check env vars |
| clw-network-timeout | Slow responses | Increase timeout, retry |
| clw-compute-failed | Job runtime error | Validate inputs, debug payload |
Cross-reference: clw-rate-limit-exceeded often precedes clw-api-exhausted. Monitor both.
Word count: 1,256. Code blocks: ~45% of content.