Skip to content

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:

json
{
  "error": "unauthorized",
  "message": "Invalid API key"
}

Solutions:

  1. Check API Key Format

    • Sandbox keys start with sk_sandbox_
    • Production keys start with sk_live_
    bash
    echo $POCKETDNS_API_KEY | cut -c1-11
    # Should output: sk_sandbox_ or sk_live_
  2. Verify Environment Variables

    javascript
    console.log('API Key set:', !!process.env.POCKETDNS_API_KEY);
    console.log('API Key prefix:', process.env.POCKETDNS_API_KEY?.substring(0, 11));
  3. Check API Endpoint

    javascript
    const config = {
      sandbox: 'https://api.sandbox.pocketdns.com',
      production: 'https://api.pocketdns.com'
    };
    
    // Ensure you're using the right endpoint for your API key
  4. Test API Key

    bash
    curl -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:

  1. Validate User Identifier

    javascript
    const 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;
    };
  2. Check Session Response

    javascript
    const 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()
    });
  3. Verify Email Format (if provided)

    javascript
    const 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:

  1. Check Login URL Validity

    javascript
    const 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;
      }
    };
  2. 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>
  3. 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;">
  4. 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:

  1. Validate DNS Record Format

    javascript
    const 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;
    };
  2. 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.8
  3. Verify TTL Settings

    javascript
    const 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:

json
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests",
  "details": {
    "limit": 100,
    "window": 60,
    "retry_after": 30
  }
}

Solutions:

  1. Implement Rate Limit Handling

    javascript
    const 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;
        }
      }
    };
  2. Add Request Caching

    javascript
    const 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;
    };
  3. Monitor Rate Limit Usage

    javascript
    const 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:

  1. 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"}'
  2. Check Webhook Signature Verification

    javascript
    const 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')
      );
    };
  3. Debug Webhook Processing

    javascript
    app.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

javascript
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: '[email protected]'
      })
    });
    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

javascript
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

javascript
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:

javascript
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:

javascript
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;
};

Built with ❤️ for PocketDNS Partners