Troubleshooting
Common issues and solutions when integrating with the Edge Query API
Authentication Issues
401 Unauthorized / INVALID_API_KEY
Symptom: API returns 401 status with error code INVALID_API_KEY.
Causes:
- API key is incorrect or has been revoked
- API key header format is wrong
- API key has been regenerated but old key is still in use
Fix:
- Verify your API key in the dashboard
- Check that the key is active (not revoked)
- Ensure header format is:
X-API-Key: your_api_key_here - Regenerate a new API key if needed and update your environment variables
401 Missing API Key / MISSING_API_KEY
Symptom: API returns 401 status with error code MISSING_API_KEY.
Causes:
X-API-Keyheader not being sent with request- Proxy or CDN is stripping headers
- Environment variable not loaded correctly
Fix:
- Test with curl to verify header is being sent:
curl -H "X-API-Key: YOUR_KEY" \ "https://api.3xx.app/v1/lookup?path=/test&projectId=YOUR_PROJECT_ID" - Check proxy/CDN configuration (some strip custom headers)
- Verify environment variables are loaded (check
console.log(process.env.REDIRECTIONS_API_KEY))
API Key Works in curl but Not in Application
Symptom: Manual curl requests work, but application requests fail.
Causes:
- Environment variable not set in application runtime
- Platform-specific environment variable loading (Edge Runtime, serverless, containers)
Fix:
Next.js:
- Ensure
.env.localexists with correct values - Restart dev server after changing
.env.local - For production, set in deployment platform (Vercel, AWS, etc.)
Node.js:
- Load with
dotenv:require('dotenv').config() - Or use Node.js 20+ native:
node --env-file=.env app.js
Nginx/Apache:
- Set in Lua script directly or use environment block
- Apache: Use
SetEnvdirective
Rate Limiting
429 Too Many Requests / RATE_LIMIT_EXCEEDED
Symptom: API returns 429 status with error code RATE_LIMIT_EXCEEDED.
Causes:
- Exceeded per-minute rate limit for your tier
- Too many concurrent requests
Rate limits by tier:
- Free: 100 requests/minute
- Pro: 1,000 requests/minute
- Enterprise: Unlimited
Fix:
- Check
X-RateLimit-Remainingresponse header to see how many requests you have left - Implement exponential backoff for retries
- Switch to sync pattern (export + local lookup) for high-traffic scenarios
- Upgrade to higher tier if needed
Example backoff implementation:
async function fetchWithBackoff(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status !== 429) {
return response;
}
// Wait 2^i seconds before retry
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
}
throw new Error('Rate limit exceeded after retries');
}Quota Exhaustion
429 Quota Exceeded / QUOTA_EXCEEDED
Symptom: API returns 429 status with error code QUOTA_EXCEEDED.
Causes:
- Exceeded monthly API request quota
- Plan quota exhausted
Quota limits by tier:
- Free: 10,000 requests/month
- Pro: 1,000,000 requests/month
- Enterprise: Unlimited
Fix:
- Check usage in dashboard
- Consider upgrading to higher tier
- Switch to sync pattern to eliminate per-request API calls:
- Fetch redirects once at startup/build time
- Store in local config file or in-memory map
- Periodic refresh (5-15 minutes) instead of per-request
Network and Connectivity
API Timeout
Symptom: Request times out without response.
Causes:
- Network connectivity issue
- Firewall blocking outbound HTTPS
- DNS resolution failure
- Origin server issue (rare)
Fix:
- Check network connectivity:
ping 1.1.1.1 - Test DNS resolution:
nslookup api.3xx.app - Check firewall rules allow outbound HTTPS (port 443)
- Test with curl:
curl -v https://api.3xx.app/health - Check status page for incidents
SSL/TLS Errors
Symptom: Certificate verification errors, SSL handshake failures.
Causes:
- Outdated TLS version (pre-1.2)
- System certificate store outdated
- Man-in-the-middle proxy with invalid certificate
Fix:
- Ensure client supports TLS 1.2 or higher
- Update system certificates:
apt-get update && apt-get install ca-certificates(Linux) - Check if corporate proxy is intercepting HTTPS
- Verify certificate chain:
openssl s_client -connect api.3xx.app:443 -showcerts
Connection Refused
Symptom: ECONNREFUSED error.
Causes:
- Wrong API URL (typo, missing https://)
- Network restriction
Fix:
- Verify API URL:
https://api.3xx.app - Check for typos in domain name
- Ensure using HTTPS (not HTTP)
No Redirect Happening
204 No Content Response
Symptom: API returns 204 status, redirect doesn't trigger.
Causes:
- Path doesn't match any redirect rule in the project
- Path encoding mismatch (URL-encoded vs plain)
- Wrong project ID
- Redirect not deployed yet
Fix:
- Verify path exists in dashboard redirect list
- Check path encoding:
- API expects URL-encoded paths:
/my%20pathfor/my path - Ensure consistent encoding between request and redirect rules
- API expects URL-encoded paths:
- Verify
projectIdparameter matches your actual project ID (check dashboard URL) - Check if redirect is in pending state (needs deployment via Build & Deploy page)
Redirect Matches in Dashboard but Not in Application
Symptom: Redirect shows in dashboard, but application gets 204.
Causes:
- Pending changes not deployed
- Caching old redirect data
- Case sensitivity mismatch
Fix:
- Deploy pending changes via dashboard Build & Deploy page
- Clear application cache (if using sync pattern)
- Restart application (if using startup-time sync)
- Check path case sensitivity (paths are case-sensitive)
Sync Pattern Issues
Sync Script Fails
Symptom: Script exits with error when calling /v1/export.
Causes:
- Invalid API key
- Network error
- Wrong export format parameter
Fix:
- Test API manually:
curl -H "X-API-Key: YOUR_KEY" \ "https://api.3xx.app/v1/export?format=csv&projectId=YOUR_PROJECT_ID" - Check API key is valid (not revoked)
- Verify network connectivity
- Ensure
formatparameter iscsvorjson
Config File Not Updating
Symptom: Sync script runs but config file has old data.
Causes:
- Non-atomic file write (partially written file)
- Permission errors
- Wrong file path
Fix:
- Use atomic file replacement pattern:
const fs = require('fs'); const tmpFile = 'redirects.tmp.json'; const finalFile = 'redirects.json'; // Write to temp file fs.writeFileSync(tmpFile, JSON.stringify(redirects)); // Atomic rename fs.renameSync(tmpFile, finalFile); - Check file permissions:
ls -la redirects.json - Verify correct output path in script
Server Not Picking Up Changes
Symptom: Config file updated but server uses old redirects.
Causes:
- Server hasn't reloaded config
- In-memory cache not invalidated
- Wrong reload mechanism
Fix:
Nginx: Graceful reload after sync:
nginx -s reloadApache: Graceful restart:
apachectl gracefulNode.js: Implement config reload without restart:
let redirectsMap = new Map();
async function reloadRedirects() {
const newMap = await loadRedirects();
redirectsMap = newMap; // Atomic swap
}
// Reload on SIGHUP
process.on('SIGHUP', reloadRedirects);Partial Config File
Symptom: Config file has incomplete data, application crashes.
Causes:
- Non-atomic write interrupted
- Script crashed mid-write
Fix:
- Always use temp file + atomic rename pattern (see above)
- Never write directly to production config file
- Add validation before rename:
const data = JSON.parse(fs.readFileSync(tmpFile, 'utf-8')); if (!Array.isArray(data) || data.length === 0) { throw new Error('Invalid redirect data'); } fs.renameSync(tmpFile, finalFile);
Performance
High Latency on Redirect Lookups
Symptom: Slow response times for redirect checks.
Causes:
- Real-time API pattern with high latency to edge
- Many sequential API calls
- No local caching
Fix:
- Switch from real-time to sync pattern:
- Eliminates per-request API calls
- Local lookups are sub-millisecond
- Implement local caching with TTL (5-15 min)
- Check edge location routing (API should route to nearest edge)
Too Many API Calls
Symptom: High API usage, quota exhaustion.
Causes:
- Real-time pattern on high-traffic site
- Middleware running on static files (bad matcher config)
- No caching
Fix:
- Next.js: Fix matcher to exclude static assets:
export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'], }; - Node.js: Add path filtering before API call:
if (req.path.startsWith('/_next/') || req.path === '/favicon.ico') { return next(); } - Switch to sync pattern for high-traffic sites
- Implement local caching
Edge Response Slow
Symptom: API responds slowly despite being edge-deployed.
Causes:
- Request not hitting nearest edge location
- Edge cache miss
- Cold start (rare)
Fix:
- Check response
CF-RAYheader to see which edge location handled request - Implement sync pattern to bypass API entirely for critical paths
- Verify DNS resolution points to Cloudflare edge
Getting Help
If you're still experiencing issues:
- Check API reference for detailed error codes: Error Codes Documentation
- Review rate limits in the API reference: API Reference
- Inspect response headers for debugging info:
X-RateLimit-Remaining- API quota remainingX-RateLimit-Reset- When quota resetsCF-RAY- Cloudflare edge location ID
- Enable debug logging in your integration to capture full request/response details
- Test with curl to isolate whether issue is in integration or API
- Check dashboard usage page to see API call patterns and identify issues