Technical Troubleshooting
Diagnose and resolve technical issues with LocallyGrown integrations, APIs, webhooks, and applications. Find solutions to common problems and learn debugging techniques.
Common API Issues
🔐 Authentication Problems
401 Unauthorized Error
Symptoms: API requests return "Unauthorized" error
Common Causes:
- Invalid or expired API key
 - Missing Authorization header
 - Wrong API key format
 - Using test key in production
 
Solutions:
- Verify API key is correct and active
 - Check Authorization header format: 
Bearer {api_key} - Ensure using live keys for production
 - Regenerate API keys if compromised
 
403 Forbidden Error
Symptoms: Valid authentication but access denied
Common Causes:
- Insufficient permissions for API key
 - Resource not accessible for your market
 - Rate limit exceeded
 - IP address restrictions
 
Solutions:
- Check API key permissions in admin panel
 - Verify market ID in requests
 - Implement rate limiting in your application
 - Contact support for IP whitelist updates
 
📡 Connection Issues
Network Timeouts
Symptoms: Requests hang or timeout
Common Causes:
- Slow network connection
 - Large payload sizes
 - Server overload
 - Firewall blocking requests
 
Solutions:
- Increase timeout values (max 30 seconds)
 - Implement retry logic with exponential backoff
 - Check firewall and proxy settings
 - Use pagination for large data sets
 
SSL/TLS Certificate Errors
Symptoms: Certificate verification failures
Common Causes:
- Outdated certificate store
 - Corporate firewall interference
 - Self-signed certificates in development
 - Clock synchronization issues
 
Solutions:
- Update system certificate store
 - Configure proxy settings correctly
 - Use proper certificates in all environments
 - Synchronize system clock
 
🔧 Error Response Handling
Improved Error Responses
What's Changed: API endpoints now consistently return JSON error responses
Error Response Format:
{
  "error": true,
  "message": "Human-readable error description",
  "code": "ERROR_CODE",
  "details": {
    // Additional context when available
  }
} Benefits:
- Consistent error format across all endpoints
 - Machine-readable error codes for automated handling
 - Helpful error messages for debugging
 - No more HTML error pages in API responses
 
Example Error Handling:
try {
  const response = await fetch('/api/orders', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
			},
    body: JSON.stringify(orderData)
	});
  const data = await response.json();
  if (!response.ok) {
    // Handle API error
    console.error(`API Error: ${data.message} (${data.code})`);
    switch (data.code) {
      case 'INVALID_PAYMENT':
        handlePaymentError(data.details);
        break;
      case 'INSUFFICIENT_STOCK':
        handleStockError(data.details);
        break;
      default:
        showGenericError(data.message);
			}
		}
	} catch (error) {
  // Handle network or parsing errors
  console.error('Request failed:', error);
	}Webhook Troubleshooting
Webhooks Not Being Delivered
Diagnostic Steps:
- Check webhook URL accessibility from external networks
 - Verify endpoint returns 200 status code
 - Test webhook URL with curl or Postman
 - Review webhook logs in admin dashboard
 
Testing Webhook Endpoint
# Test webhook endpoint accessibility
curl -X POST https://your-app.com/webhooks/locallygrown \
  -H "Content-Type: application/json" \
  -H "X-LocallyGrown-Signature: test" \
  -d='{"test": true}'
# Expected response: 200 OK
# Check webhook logs
tail -f /var/log/your-app/webhooks.logSignature Verification Failures
Common Problems:
- Incorrect webhook secret
 - Wrong payload encoding
 - Modified request body
 - Timing-based signature mismatches
 
Debug Signature Verification
// Log signature components for debugging
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-locallygrown-signature'];
  const payload = JSON.stringify(req.body);
  console.log('Received signature:', signature);
  console.log('Payload length:', payload.length);
  console.log('Payload preview:', payload.substring(0, 100));
  // Your verification logic here
  const isValid = verifySignature(payload, signature, webhookSecret);
  console.log('Signature valid:', isValid);
  if (!isValid) {
    console.log('Expected signature would be:', generateSignature(payload, webhookSecret));
    return res.status(401).send('Invalid signature');
  }
  res.status(200).send('OK');
});Duplicate Event Processing
Symptoms: Same event processed multiple times
Solutions:
- Implement idempotency using event IDs
 - Use database constraints to prevent duplicates
 - Respond with 200 for already processed events
 - Implement proper error handling
 
Idempotency Implementation
const processedEvents = new Set();
app.post('/webhook', async (req, res) => {
  const { id, type, data } = req.body;
  // Check if event already processed
  if (processedEvents.has(id) || await isEventInDatabase(id)) {
    console.log(`Event ${id} already processed`);
    return res.status(200).send('Already processed');
  }
  try {
    await processEvent(type, data);
    await saveEventToDatabase(id, type, data);
    processedEvents.add(id);
    res.status(200).send('OK');
  } catch (error) {
    console.error(`Failed to process event ${id}:`, error);
    res.status(500).send('Processing failed');
  }
});Payment Integration Issues
Payment Failures
Common Error Codes:
- card_declined - Card issuer declined the payment
 - insufficient_funds - Not enough money in account
 - invalid_card - Card number or details invalid
 - expired_card - Card past expiration date
 
Debugging Steps:
- Check Stripe/payment processor logs
 - Verify card details and test with known good card
 - Test in sandbox mode first
 - Review payment method configuration
 
Webhook Event Mismatches
Symptoms: Payment status in LocallyGrown doesn't match processor
Solutions:
- Verify webhook endpoints are configured correctly
 - Check webhook event filtering
 - Implement webhook retry handling
 - Monitor webhook delivery logs
 
Integration Performance Issues
Rate Limiting Problems
429 Too Many Requests
Symptoms: API returns rate limit errors
Solutions:
- Implement exponential backoff retry logic
 - Use batch operations where available
 - Cache frequently accessed data
 - Spread requests over time
 
Rate Limiting with Retry Logic
async function apiRequestWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After') || Math.pow(2, attempt);
        console.log(`Rate limited, retrying after ${retryAfter}s`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      return response;
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
    }
  }
}Slow Response Times
Performance Optimization
- Use pagination - Request data in smaller chunks
 - Implement caching - Cache static or slow-changing data
 - Parallel requests - Make multiple API calls concurrently
 - Filter data - Request only needed fields and records
 
Parallel API Requests
// Instead of sequential requests
const orders = await getOrders();
const customers = await getCustomers();
const products = await getProducts();
// Use parallel requests
const [orders, customers, products] = await Promise.all([
  getOrders(),
  getCustomers(),
  getProducts()
]);
// With error handling
const results = await Promise.allSettled([
  getOrders(),
  getCustomers(),
  getProducts()
]);
results.forEach((result, index) => {
  if (result.status === 'rejected') {
    console.error(`Request ${index} failed:`, result.reason);
  }
});Debugging Tools and Techniques
API Request Debugging
curl Commands
Test API endpoints directly:
# Test authentication
curl -H "Authorization: Bearer sk_test_..." \
     https://api.locallygrown.net/v1/orders
# Test with verbose output
curl -v -X POST \
     -H "Authorization: Bearer sk_test_..." \
     -H "Content-Type: application/json" \
     -d='{"test": "data"}' \
     https://api.locallygrown.net/v1/webhook-test
# Save response to file
curl -o response.json \
     -H "Authorization: Bearer sk_test_..." \
     https://api.locallygrown.net/v1/customersNetwork Monitoring
Monitor API traffic and responses:
- Browser DevTools - Network tab for web requests
 - Wireshark - Detailed network packet analysis
 - Charles Proxy - HTTP debugging proxy
 - Postman - API testing and debugging
 
Logging Best Practices
What to Log
- Request details - Method, URL, headers (not auth tokens)
 - Response status - Status codes and error messages
 - Timing information - Request duration and timestamps
 - User context - User ID, market ID, session info
 
Structured Logging Example
const logger = require('winston');
// Configure structured logging
const apiLogger = logger.createLogger({
  format: logger.format.combine(
    logger.format.timestamp(),
    logger.format.json()
  ),
  transports: [
    new logger.transports.File({ filename: 'api.log' })
  ]
});
// Log API requests
function logApiRequest(req, res, responseTime) {
  apiLogger.info({
    type: 'api_request',
    method: req.method,
    url: req.url,
    statusCode: res.statusCode,
    responseTime: responseTime,
    userAgent: req.headers['user-agent'],
    userId: req.user?.id,
    marketId: req.headers['x-market-id']
  });
}
// Log errors with context
function logError(error, context) {
  apiLogger.error({
    type: 'error',
    message: error.message,
    stack: error.stack,
    context: context,
    timestamp: new Date().toISOString()
  });
}Environment-Specific Issues
Development Environment
Common Issues:
- Using production API keys in development
 - SSL certificate problems with localhost
 - CORS issues with browser-based requests
 - Environment variable configuration
 
Solutions:
- Use test API keys for development
 - Configure local SSL or use tunneling tools (ngrok)
 - Set up proper CORS headers
 - Use .env files for configuration
 
Production Environment
Common Issues:
- Environment variable mismatches
 - Network connectivity restrictions
 - Load balancer configuration problems
 - Database connection issues
 
Solutions:
- Validate environment configuration on deployment
 - Configure firewall rules for API access
 - Ensure load balancer passes headers correctly
 - Implement connection pooling and health checks
 
Environment Configuration Check
// Validate environment configuration
function validateEnvironment() {
  const required = [
    'LOCALLYGROWN_API_KEY',
    'LOCALLYGROWN_WEBHOOK_SECRET',
    'DATABASE_URL',
    'REDIS_URL'
  ];
  const missing = required.filter(key => !process.env[key]);
  if (missing.length > 0) {
    console.error('Missing required environment variables:', missing);
    process.exit(1);
  }
  // Validate API key format
  const apiKey = process.env.LOCALLYGROWN_API_KEY;
  if (!apiKey.startsWith('sk_')) {
    console.error('Invalid API key format');
    process.exit(1);
  }
  console.log('Environment configuration validated');
}
validateEnvironment();Error Monitoring and Alerting
Monitoring Setup
- Error tracking - Use Sentry, Bugsnag, or similar services
 - API monitoring - Monitor endpoint availability and response times
 - Log aggregation - Centralize logs with ELK stack or similar
 - Metrics collection - Track business and technical metrics
 
Key Metrics to Monitor
API Health
- Response time percentiles
 - Error rate by endpoint
 - Rate limit utilization
 - Authentication failures
 
Integration Health
- Webhook delivery success rate
 - Data synchronization lag
 - Failed payment processing
 - Queue processing delays
 
Business Metrics
- Order processing time
 - Customer signup rate
 - Revenue tracking accuracy
 - Inventory sync reliability
 
Getting Additional Help
Support Resources
- Technical documentation - Complete API and integration guides
 - Developer support - Email support for integration questions
 - Community forums - Connect with other developers
 - Status page - Real-time system status and incident updates
 
When Contacting Support
Include these details for faster resolution:
- Error messages - Complete error text and codes
 - Request details - API endpoint, method, payload (sanitized)
 - Response details - Status codes, headers, response body
 - Environment info - Development vs production, library versions
 - Steps to reproduce - Clear reproduction steps
 - Expected vs actual behavior - What should happen vs what happens
 
Support Request Template
Subject: API Integration Issue - [Brief Description]
Environment: Production/Development
API Endpoint: GET /v1/orders
Error Code: 429
Response Time: 2024-01-15 10:30:00 UTC
Error Message:
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests"
}
Request Details:
- Authorization: Bearer rk_live_xxx... (last 4 characters)
- Content-Type: application/json
- User-Agent: MyApp/1.0
Steps to Reproduce:
1. Make 100 API requests in quick succession
2. Error occurs on request #51
Expected Behavior:
Requests should be processed with appropriate rate limiting
Additional Context:
- This started happening after deploying version 2.1
- Same code works fine in development environment