Skip to main content

Common Issues

Quick solutions to the most frequent problems developers encounter.
Error: Invalid API key providedSolutions:
  • Verify your API key is correctly copied from Nevermined App
  • Check environment variable is loaded: console.log(process.env.NVM_API_KEY)
  • Ensure you’re using the right key for your environment (test vs production)
  • Generate a new API key if the current one expired
// Debug API key issues
const payments = Payments.getInstance({
  nvmApiKey: process.env.NVM_API_KEY || 'key-not-found',
  environment: 'testing',
  debug: true // Enable debug logs
})
Error: Network request failed or ECONNREFUSEDSolutions:
  • Check your internet connection
  • Verify Nevermined services are accessible
  • Try a different environment (testing vs production)
  • Check if you’re behind a corporate firewall
  • Implement retry logic for transient failures
// Test connection
try {
  const status = await payments.getServiceStatus()
  console.log('Service status:', status)
} catch (error) {
  console.error('Connection failed:', error)
}
Error: Insufficient credits for redemptionSolutions:
  • Check subscriber’s balance before processing
  • Verify credit consumption amount is correct
  • Ensure plan hasn’t expired (for time-based plans)
  • Provide clear feedback about credit requirements
const balance = await payments.getPlanBalance(planId, subscriberAddress)
console.log(`Credits available: ${balance.credits}`)
console.log(`Is subscriber: ${balance.isSubscriber}`)
console.log(`Plan type: ${balance.planType}`)
Error: Invalid request signature or validation failsSolutions:
  • Ensure all required parameters are provided
  • Check signature is in the correct header: x-nvm-query-signature
  • Verify subscriber address matches the signer
  • Make sure plan and agent IDs are correct
// Debug validation
console.log('Validation params:', {
  planId,
  agentId,
  subscriberAddress,
  signature: req.headers['x-nvm-query-signature']
})
Error: Agent not found or 404 errorsSolutions:
  • Verify agent ID is correct
  • Check agent was successfully registered
  • Ensure you’re using the right environment
  • Try fetching agent details directly
try {
  const agent = await payments.getAgent(agentId)
  console.log('Agent found:', agent.metadata.name)
} catch (error) {
  console.error('Agent lookup failed:', error)
}
Error: Plan has expired for time-based subscriptionsSolutions:
  • Check plan expiration: balance.expiresAt
  • Remind users to renew before expiration
  • Implement grace periods if appropriate
  • Provide easy renewal options
const balance = await payments.getPlanBalance(planId, subscriberAddress)
if (balance.planType === 'TIME' && balance.expiresAt) {
  const expiresIn = balance.expiresAt - Date.now()
  if (expiresIn < 86400000) { // Less than 24 hours
    console.warn('Plan expires soon!')
  }
}

Debugging Techniques

Enable Debug Logging

Get detailed logs from the SDK:
const payments = Payments.getInstance({
  nvmApiKey: process.env.NVM_API_KEY,
  environment: 'testing',
  debug: true // Enable verbose logging
})

// Also set environment variable
process.env.DEBUG = 'nevermined:*'

Test Individual Components

Break down complex operations to isolate issues:
async function debugWorkflow() {
  console.log('1. Testing connection...')
  try {
    const status = await payments.getServiceStatus()
    console.log('✓ Connected:', status)
  } catch (error) {
    console.error('✗ Connection failed:', error)
    return
  }

  console.log('2. Fetching agent...')
  try {
    const agent = await payments.getAgent(agentId)
    console.log('✓ Agent found:', agent.metadata.name)
  } catch (error) {
    console.error('✗ Agent not found:', error)
    return
  }

  console.log('3. Checking plan...')
  try {
    const plan = await payments.getPlan(planId)
    console.log('✓ Plan found:', plan.metadata)
  } catch (error) {
    console.error('✗ Plan not found:', error)
    return
  }

  console.log('4. Validating access...')
  try {
    const isValid = await payments.isValidRequest(
      planId, agentId, subscriberAddress, signature
    )
    console.log('✓ Access valid:', isValid)
  } catch (error) {
    console.error('✗ Validation failed:', error)
  }
}

Use Testing Environment

Always test in the testing environment first:
// Development workflow
const environments = {
  local: 'local',
  test: 'testing',  // Base Sepolia testnet
  prod: 'production' // Base Mainnet
}

const payments = Payments.getInstance({
  nvmApiKey: process.env.NVM_API_KEY,
  environment: environments[process.env.NODE_ENV] || 'testing'
})

Environment-Specific Issues

Local Development

Problem: Cross-Origin Resource Sharing errors in browserSolution:
// Add CORS middleware
import cors from 'cors'

app.use(cors({
  origin: process.env.FRONTEND_URL || 'http://localhost:3000',
  credentials: true,
  allowedHeaders: ['Content-Type', 'x-nvm-query-signature']
}))

Production Issues

Symptoms: Slow response times, timeoutsSolutions:
// 1. Implement caching
import NodeCache from 'node-cache'
const cache = new NodeCache({ stdTTL: 300 })

async function getCachedAgent(agentId: string) {
  const cached = cache.get(agentId)
  if (cached) return cached
  
  const agent = await payments.getAgent(agentId)
  cache.set(agentId, agent)
  return agent
}

// 2. Use connection pooling
// 3. Optimize database queries
// 4. Implement request queuing
Symptoms: Increased 5xx errors, failed validationsSolutions:
  • Check service health endpoints
  • Verify API rate limits aren’t exceeded
  • Review error logs for patterns
  • Implement circuit breakers
  • Scale infrastructure if needed
Symptoms: Transactions failing, credits not updatingSolutions:
  • Verify wallet has sufficient gas
  • Check token contract addresses
  • Ensure builder address is correct
  • Monitor blockchain congestion
  • Implement payment retry logic

Validation Issues

Request Validation Checklist

// Comprehensive validation
function validateRequest(req: Request): ValidationResult {
  const errors = []

  // 1. Check required body parameters
  const required = ['planId', 'agentId', 'subscriberAddress']
  for (const field of required) {
    if (!req.body[field]) {
      errors.push(`Missing required field: ${field}`)
    }
  }

  // 2. Check signature header
  if (!req.headers['x-nvm-query-signature']) {
    errors.push('Missing signature header: x-nvm-query-signature')
  }

  // 3. Validate address format
  const addressRegex = /^0x[a-fA-F0-9]{40}$/
  if (req.body.subscriberAddress && !addressRegex.test(req.body.subscriberAddress)) {
    errors.push('Invalid Ethereum address format')
  }

  // 4. Validate IDs format
  const idRegex = /^[a-zA-Z0-9_-]+$/
  if (req.body.planId && !idRegex.test(req.body.planId)) {
    errors.push('Invalid plan ID format')
  }

  return {
    valid: errors.length === 0,
    errors
  }
}

// Use in endpoint
app.post('/api/query', async (req, res) => {
  const validation = validateRequest(req)
  if (!validation.valid) {
    return res.status(400).json({
      error: 'Invalid request',
      details: validation.errors
    })
  }
  
  // Continue with Nevermined validation...
})

Getting Help

Debug Information Template

When seeking help, provide this information:
async function gatherDebugInfo() {
  const info = {
    // Environment
    nodeVersion: process.version,
    environment: process.env.NODE_ENV,
    neverminedEnv: payments.config.environment,
    
    // SDK Version
    sdkVersion: require('@nevermined-io/payments/package.json').version,
    
    // Configuration (sanitized)
    hasApiKey: !!process.env.NVM_API_KEY,
    apiKeyPrefix: process.env.NVM_API_KEY?.substring(0, 8) + '...',
    
    // Error details
    errorMessage: 'Your error message',
    errorCode: 'Error code if available',
    errorStack: 'Stack trace',
    
    // Request details
    endpoint: '/api/query',
    method: 'POST',
    headers: {
      'content-type': 'application/json',
      'x-nvm-query-signature': 'present'
    },
    
    // Timestamps
    timestamp: new Date().toISOString(),
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
  }
  
  return info
}

// Save to file for sharing
const debugInfo = await gatherDebugInfo()
fs.writeFileSync('debug-info.json', JSON.stringify(debugInfo, null, 2))

Support Resources

Health Check Endpoint

Implement a comprehensive health check:
app.get('/health', async (req, res) => {
  const health = {
    status: 'checking',
    timestamp: new Date().toISOString(),
    checks: {}
  }

  // Check Nevermined connection
  try {
    await payments.getServiceStatus()
    health.checks.nevermined = 'ok'
  } catch (error) {
    health.checks.nevermined = 'error'
    health.status = 'unhealthy'
  }

  // Check database
  try {
    await db.ping()
    health.checks.database = 'ok'
  } catch (error) {
    health.checks.database = 'error'
    health.status = 'unhealthy'
  }

  // Check Redis cache
  try {
    await redis.ping()
    health.checks.cache = 'ok'
  } catch (error) {
    health.checks.cache = 'error'
  }

  // Overall status
  if (health.status === 'checking') {
    health.status = 'healthy'
  }

  res.status(health.status === 'healthy' ? 200 : 503).json(health)
})

Prevention Tips

Most issues can be prevented with proper setup and testing. Follow these guidelines:
  • Always test in the testing environment first
  • Implement comprehensive error handling
  • Add monitoring and alerting
  • Keep the SDK updated
  • Follow security best practices
  • Document your integration thoroughly
Need more help? Join our Discord community where developers are ready to assist!