Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/api/gotchas.md
1# Gotchas & Troubleshooting23## Rate Limits & 429 Errors45**Actual Limits:**6- **1200 requests / 5 minutes** per user/token (global)7- **200 requests / second** per IP address8- **GraphQL: 320 / 5 minutes** (cost-based)910**SDK Behavior:**11- Auto-retry with exponential backoff (default 2 retries, Go: 10)12- Respects `Retry-After` header13- Throws `RateLimitError` after exhausting retries1415**Solution:**1617```typescript18// Increase retries for rate-limit-heavy workflows19const client = new Cloudflare({ maxRetries: 5 });2021// Add application-level throttling22import pLimit from 'p-limit';23const limit = pLimit(10); // Max 10 concurrent requests24```2526## SDK-Specific Issues2728### Go: Required Field Wrapper2930**Problem:** Go SDK requires `cloudflare.F()` wrapper for optional fields.3132```go33// ❌ WRONG - Won't compile or send field34client.Zones.New(ctx, cloudflare.ZoneNewParams{35Name: "example.com",36})3738// ✅ CORRECT39client.Zones.New(ctx, cloudflare.ZoneNewParams{40Name: cloudflare.F("example.com"),41Account: cloudflare.F(cloudflare.ZoneNewParamsAccount{42ID: cloudflare.F("account-id"),43}),44})45```4647**Why:** Distinguishes between zero value, null, and omitted fields.4849### Python: Async vs Sync Clients5051**Problem:** Using sync client in async context or vice versa.5253```python54# ❌ WRONG - Can't await sync client55from cloudflare import Cloudflare56client = Cloudflare()57await client.zones.list() # TypeError5859# ✅ CORRECT - Use AsyncCloudflare60from cloudflare import AsyncCloudflare61client = AsyncCloudflare()62await client.zones.list()63```6465## Token Permission Errors (403)6667**Problem:** API returns 403 Forbidden despite valid token.6869**Cause:** Token lacks required permissions (scope).7071**Scopes Required:**7273| Operation | Required Scope |74|-----------|----------------|75| List zones | Zone:Read (zone-level or account-level) |76| Create zone | Zone:Edit (account-level) |77| Edit DNS | DNS:Edit (zone-level) |78| Deploy Worker | Workers Script:Edit (account-level) |79| Read KV | Workers KV Storage:Read |80| Write KV | Workers KV Storage:Edit |8182**Solution:** Re-create token with correct permissions in Dashboard → My Profile → API Tokens.8384## Pagination Truncation8586**Problem:** Only getting first 20 results (default page size).8788**Solution:** Use auto-pagination iterators.8990```typescript91// ❌ WRONG - Only first page (20 items)92const page = await client.zones.list();9394// ✅ CORRECT - All results95const zones = [];96for await (const zone of client.zones.list()) {97zones.push(zone);98}99```100101## Workers Subrequests102103**Problem:** Rate limit hit faster than expected in Workers.104105**Cause:** Workers subrequests count as separate API calls.106107**Solution:** Use bindings instead of REST API in Workers (see ../bindings/).108109```typescript110// ❌ WRONG - REST API in Workers (counts against rate limit)111const client = new Cloudflare({ apiToken: env.CLOUDFLARE_API_TOKEN });112const zones = await client.zones.list();113114// ✅ CORRECT - Use bindings (no rate limit)115// Access via env.MY_BINDING116```117118## Authentication Errors (401)119120**Problem:** "Authentication failed" or "Invalid token"121122**Causes:**123- Token expired124- Token deleted/revoked125- Token not set in environment126- Wrong token format127128**Solution:**129130```typescript131// Verify token is set132if (!process.env.CLOUDFLARE_API_TOKEN) {133throw new Error('CLOUDFLARE_API_TOKEN not set');134}135136// Test token137const user = await client.user.tokens.verify();138console.log('Token valid:', user.status);139```140141## Timeout Errors142143**Problem:** Request times out (default 60s).144145**Cause:** Large operations (bulk DNS, zone transfers).146147**Solution:** Increase timeout or split operations.148149```typescript150// Increase timeout151const client = new Cloudflare({152timeout: 300000, // 5 minutes153});154155// Or split operations156const batchSize = 100;157for (let i = 0; i < records.length; i += batchSize) {158const batch = records.slice(i, i + batchSize);159await processBatch(batch);160}161```162163## Zone Not Found (404)164165**Problem:** Zone ID valid but returns 404.166167**Causes:**168- Zone not in account associated with token169- Zone deleted170- Wrong zone ID format171172**Solution:**173174```typescript175// List all zones to find correct ID176for await (const zone of client.zones.list()) {177console.log(zone.id, zone.name);178}179```180181## Limits Reference182183| Resource/Limit | Value | Notes |184|----------------|-------|-------|185| API rate limit | 1200/5min | Per user/token |186| IP rate limit | 200/sec | Per IP |187| GraphQL rate limit | 320/5min | Cost-based |188| Parallel requests (recommended) | < 10 | Avoid overwhelming API |189| Default page size | 20 | Use auto-pagination |190| Max page size | 50 | Some endpoints |191192## Best Practices193194**Security:**195- Never commit tokens196- Use minimal permissions197- Rotate tokens regularly198- Set token expiration199200**Performance:**201- Batch operations202- Use pagination wisely203- Cache responses204- Handle rate limits205206**Code Organization:**207208```typescript209// Create reusable client instance210export const cfClient = new Cloudflare({211apiToken: process.env.CLOUDFLARE_API_TOKEN,212maxRetries: 5,213});214215// Wrap common operations216export async function getZoneDetails(zoneId: string) {217return await cfClient.zones.get({ zone_id: zoneId });218}219```220221## See Also222223- [api.md](./api.md) - Error types, authentication224- [configuration.md](./configuration.md) - Timeout/retry configuration225- [patterns.md](./patterns.md) - Error handling patterns226