Troubleshooting
This guide helps you diagnose and fix common issues with your PocketDNS integration.
Common Issues
API Authentication Problems
Issue: Getting 401 Unauthorized errors
Symptoms:
{
"error": "unauthorized",
"message": "Invalid API key"
}Solutions:
Check API Key Format
- Sandbox keys start with
sk_sandbox_ - Production keys start with
sk_live_
bashecho $POCKETDNS_API_KEY | cut -c1-11 # Should output: sk_sandbox_ or sk_live_- Sandbox keys start with
Verify Environment Variables
javascriptconsole.log('API Key set:', !!process.env.POCKETDNS_API_KEY); console.log('API Key prefix:', process.env.POCKETDNS_API_KEY?.substring(0, 11));Check API Endpoint
javascriptconst config = { sandbox: 'https://api.sandbox.pocketdns.com', production: 'https://api.pocketdns.com' }; // Ensure you're using the right endpoint for your API keyTest API Key
bashcurl -H "Authorization: Bearer YOUR_API_KEY" \ https://api.sandbox.pocketdns.com/api/v1/health
Session Creation Failures
Issue: User session creation failing
Symptoms:
- Empty or invalid login URLs
- Sessions expiring immediately
- Users can't access the embed interface
Solutions:
Validate User Identifier
javascriptconst validateUserIdentifier = (identifier) => { if (!identifier || typeof identifier !== 'string') { throw new Error('User identifier must be a non-empty string'); } if (identifier.length > 255) { throw new Error('User identifier too long (max 255 chars)'); } if (!/^[a-zA-Z0-9_-]+$/.test(identifier)) { throw new Error('User identifier can only contain letters, numbers, underscores, and hyphens'); } return identifier; };Check Session Response
javascriptconst session = await createUserSession('user_123'); console.log('Session created:', { hasLoginUrl: !!session.login_url, expiresAt: session.expires_at, isExpired: new Date(session.expires_at) < new Date() });Verify Email Format (if provided)
javascriptconst validateEmail = (email) => { if (!email) return null; // Email is optional const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { throw new Error('Invalid email format'); } return email; };
Iframe Loading Issues
Issue: Embedded iframe not loading or displaying errors
Symptoms:
- Blank iframe
- "This site can't be reached" errors
- CORS errors in console
- Iframe shows error page
Solutions:
Check Login URL Validity
javascriptconst validateLoginUrl = (loginUrl) => { try { const url = new URL(loginUrl); const expectedHost = process.env.NODE_ENV === 'production' ? 'embed.pocketdns.com' : 'embed.sandbox.pocketdns.com'; if (url.hostname !== expectedHost) { console.warn(`Unexpected embed host: ${url.hostname}`); } return true; } catch (error) { console.error('Invalid login URL:', error); return false; } };Verify Iframe Configuration
html<!-- Ensure iframe has required attributes --> <iframe src="{login_url}" width="100%" height="600px" frameborder="0" allow="payment" sandbox="allow-scripts allow-same-origin allow-forms allow-popups" title="PocketDNS Domain Interface"> </iframe>Check CORS and CSP Settings
html<!-- Add to your page head if needed --> <meta http-equiv="Content-Security-Policy" content="frame-src embed.pocketdns.com embed.sandbox.pocketdns.com;">Debug Network Issues
javascript// Test if embed URL is reachable const testEmbedUrl = async (loginUrl) => { try { const response = await fetch(loginUrl, { method: 'HEAD' }); console.log('Embed URL status:', response.status); return response.ok; } catch (error) { console.error('Embed URL unreachable:', error); return false; } };
DNS Record Issues
Issue: DNS records not working as expected
Symptoms:
- DNS records not propagating
- Website not accessible after DNS changes
- Email not working with MX records
Solutions:
Validate DNS Record Format
javascriptconst validateDNSRecord = (record) => { const validators = { A: (content) => /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(content), AAAA: (content) => /^[0-9a-fA-F:]+$/.test(content), CNAME: (content) => /^[a-zA-Z0-9.-]+$/.test(content), MX: (content) => /^\d+ [a-zA-Z0-9.-]+$/.test(content), TXT: () => true // TXT records can contain any text }; const validator = validators[record.type]; if (!validator || !validator(record.content)) { throw new Error(`Invalid ${record.type} record content: ${record.content}`); } return true; };Check DNS Propagation
bash# Check if DNS records are propagating dig @8.8.8.8 example.com A dig @1.1.1.1 example.com A # Check from multiple locations nslookup example.com 8.8.8.8Verify TTL Settings
javascriptconst recommendedTTLs = { A: 300, // 5 minutes AAAA: 300, // 5 minutes CNAME: 300, // 5 minutes MX: 3600, // 1 hour TXT: 300 // 5 minutes }; const checkTTL = (record) => { const recommended = recommendedTTLs[record.type]; if (record.ttl > recommended * 4) { console.warn(`High TTL for ${record.type} record: ${record.ttl}s (recommended: ${recommended}s)`); } };
Rate Limiting Issues
Issue: Getting 429 "Too Many Requests" errors
Symptoms:
{
"error": "rate_limit_exceeded",
"message": "Too many requests",
"details": {
"limit": 100,
"window": 60,
"retry_after": 30
}
}Solutions:
Implement Rate Limit Handling
javascriptconst handleRateLimit = async (operation, maxRetries = 3) => { for (let attempt = 0; attempt < maxRetries; attempt++) { try { return await operation(); } catch (error) { if (error.status === 429 && attempt < maxRetries - 1) { const retryAfter = error.details?.retry_after || Math.pow(2, attempt); console.log(`Rate limited. Retrying in ${retryAfter} seconds...`); await new Promise(resolve => setTimeout(resolve, retryAfter * 1000)); continue; } throw error; } } };Add Request Caching
javascriptconst cache = new Map(); const CACHE_TTL = 5 * 60 * 1000; // 5 minutes const cachedApiCall = async (key, apiCall) => { const cached = cache.get(key); if (cached && Date.now() - cached.timestamp < CACHE_TTL) { return cached.data; } const data = await apiCall(); cache.set(key, { data, timestamp: Date.now() }); return data; };Monitor Rate Limit Usage
javascriptconst trackRateLimit = (response) => { const limit = response.headers.get('X-RateLimit-Limit'); const remaining = response.headers.get('X-RateLimit-Remaining'); const reset = response.headers.get('X-RateLimit-Reset'); console.log(`Rate limit: ${remaining}/${limit} remaining, resets at ${new Date(reset * 1000)}`); if (remaining < 10) { console.warn('Approaching rate limit!'); } };
Webhook Issues
Issue: Webhooks not being received or processed
Symptoms:
- Missing webhook notifications
- Webhook signature verification failures
- Webhook endpoint returning errors
Solutions:
Verify Webhook Endpoint
bash# Test if your webhook endpoint is accessible curl -X POST https://yourdomain.com/webhook/pocketdns \ -H "Content-Type: application/json" \ -d '{"test": "payload"}'Check Webhook Signature Verification
javascriptconst crypto = require('crypto'); const verifyWebhookSignature = (payload, signature, secret) => { if (!signature || !signature.startsWith('sha256=')) { console.error('Missing or invalid signature format'); return false; } const expectedSignature = crypto .createHmac('sha256', secret) .update(payload, 'utf8') .digest('hex'); const receivedSignature = signature.replace('sha256=', ''); return crypto.timingSafeEqual( Buffer.from(expectedSignature, 'hex'), Buffer.from(receivedSignature, 'hex') ); };Debug Webhook Processing
javascriptapp.post('/webhook/pocketdns', (req, res) => { console.log('Webhook received:', { headers: req.headers, body: req.body, timestamp: new Date().toISOString() }); try { // Process webhook res.status(200).json({ received: true }); } catch (error) { console.error('Webhook processing failed:', error); res.status(500).json({ error: error.message }); } });
Diagnostic Tools
API Health Check
const checkAPIHealth = async () => {
const checks = {
apiConnectivity: false,
authentication: false,
userCreation: false,
domainRetrieval: false
};
try {
// Test API connectivity
const healthResponse = await fetch('https://api.pocketdns.com/health');
checks.apiConnectivity = healthResponse.ok;
// Test authentication
const authResponse = await fetch('https://api.pocketdns.com/api/v1/users', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.POCKETDNS_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_identifier: 'health_check_user',
email: 'test@example.com'
})
});
checks.authentication = authResponse.status !== 401;
checks.userCreation = authResponse.ok;
// Test domain retrieval
const domainResponse = await fetch(
'https://api.pocketdns.com/api/v1/users/health_check_user/domains',
{
headers: {
'Authorization': `Bearer ${process.env.POCKETDNS_API_KEY}`
}
}
);
checks.domainRetrieval = domainResponse.ok || domainResponse.status === 404;
} catch (error) {
console.error('Health check error:', error);
}
return checks;
};Configuration Validator
const validateConfiguration = () => {
const issues = [];
// Check environment variables
if (!process.env.POCKETDNS_API_KEY) {
issues.push('POCKETDNS_API_KEY environment variable not set');
} else {
const key = process.env.POCKETDNS_API_KEY;
if (!key.startsWith('sk_sandbox_') && !key.startsWith('sk_live_')) {
issues.push('POCKETDNS_API_KEY has invalid format');
}
if (process.env.NODE_ENV === 'production' && key.startsWith('sk_sandbox_')) {
issues.push('Using sandbox API key in production environment');
}
}
// Check webhook configuration
if (!process.env.POCKETDNS_WEBHOOK_SECRET) {
issues.push('POCKETDNS_WEBHOOK_SECRET environment variable not set');
}
// Check HTTPS
if (process.env.NODE_ENV === 'production' && process.env.DISABLE_HTTPS !== 'true') {
// Add HTTPS checks here
}
return {
valid: issues.length === 0,
issues
};
};Network Diagnostics
const diagnoseNetworkIssues = async () => {
const tests = {
dns: false,
connectivity: false,
latency: null,
ssl: false
};
try {
// Test DNS resolution
const dns = require('dns').promises;
await dns.resolve('api.pocketdns.com');
tests.dns = true;
// Test connectivity and measure latency
const start = Date.now();
const response = await fetch('https://api.pocketdns.com/health', {
timeout: 10000
});
tests.latency = Date.now() - start;
tests.connectivity = response.ok;
tests.ssl = response.url.startsWith('https://');
} catch (error) {
console.error('Network diagnostic error:', error);
}
return tests;
};Debug Mode
Enable debug mode for verbose logging:
const DEBUG = process.env.DEBUG === 'pocketdns' || process.env.NODE_ENV === 'development';
const debugLog = (...args) => {
if (DEBUG) {
console.log('[PocketDNS Debug]', new Date().toISOString(), ...args);
}
};
// Usage throughout your code
debugLog('Creating user session for:', userIdentifier);
debugLog('API response:', response.status, response.headers);
debugLog('Session created:', session);Getting Help
Information to Collect
When reporting issues, collect this information:
const collectDiagnosticInfo = async () => {
const info = {
timestamp: new Date().toISOString(),
environment: process.env.NODE_ENV,
nodeVersion: process.version,
apiKeyPrefix: process.env.POCKETDNS_API_KEY?.substring(0, 11) || 'not-set',
configuration: validateConfiguration(),
apiHealth: await checkAPIHealth(),
networkDiagnostics: await diagnoseNetworkIssues()
};
return info;
};