Troubleshooting

Common issues and solutions when using Shade402.

Payment Issues

Payment Not Detected

Problem: Server doesn't detect payment authorization.

Solutions:

  • Check that X-Payment-Authorization header is included

  • Verify header is base64-encoded JSON

  • Check that payment authorization format is correct

  • Ensure middleware is processing the header

// Debug: Log headers
app.use((req, res, next) => {
  console.log('Headers:', req.headers);
  next();
});

Payment Verification Fails

Problem: Payment verification fails even though transaction exists.

Solutions:

  • Check RPC endpoint is correct and accessible

  • Verify network matches (devnet vs mainnet)

  • Ensure transaction is confirmed on blockchain

  • Check transaction signature is valid

  • Verify payment addresses match

// Enable detailed logging
initX402({
  // ... config ...
  autoVerify: true,
});

// Check transaction manually
const processor = new SolanaPaymentProcessor(rpcUrl);
const isValid = await processor.verifyPayment(request, authorization);
console.log('Verification result:', isValid);

Payment Expired

Problem: Payment request expires before payment is made.

Solutions:

  • Increase expiration time

  • Make payment faster

  • Check system clock synchronization

  • Use shorter expiration for automated flows

// Increase expiration time
paymentRequired({
  amount: '0.01',
  expiresIn: 600, // 10 minutes instead of default 5
});

Insufficient Funds

Problem: Wallet doesn't have enough tokens.

Solutions:

  • Check wallet balance

  • Ensure correct token mint address

  • Verify token account exists

  • Add funds to wallet

// Check balance
const processor = new SolanaPaymentProcessor(rpcUrl);
const balance = await processor.getTokenBalance(
  walletPublicKey,
  tokenMint
);
console.log('Balance:', balance);

Client Issues

Cannot Connect to RPC

Problem: Client cannot connect to Solana RPC endpoint.

Solutions:

  • Check RPC URL is correct

  • Verify network connectivity

  • Try different RPC endpoint

  • Check rate limits on RPC provider

// Test RPC connection
const connection = new Connection(rpcUrl);
const version = await connection.getVersion();
console.log('RPC version:', version);

Transaction Broadcast Fails

Problem: Transaction fails to broadcast.

Solutions:

  • Check network congestion

  • Verify recent blockhash

  • Ensure sufficient SOL for fees

  • Retry transaction

// Retry with new blockhash
try {
  const txHash = await processor.signAndSendTransaction(tx, wallet);
} catch (error) {
  // Retry with new transaction
  const newTx = await processor.createPaymentTransaction(request, amount, wallet);
  const txHash = await processor.signAndSendTransaction(newTx, wallet);
}

URL Validation Errors

Problem: Client rejects localhost URLs.

Solutions:

  • Enable allowLocal for development

  • Use production URLs in production

  • Check URL format is correct

// For local development only
const client = new X402Client(wallet, rpcUrl, undefined, true);

Server Issues

402 Response Not Sent

Problem: Server doesn't send 402 response when payment required.

Solutions:

  • Check middleware is applied correctly

  • Verify payment authorization header is missing

  • Ensure error middleware is after routes

  • Check middleware order

// Verify middleware order
app.use(express.json());
app.use(paymentRequired({ amount: '0.01' })); // Route-specific
app.use(x402ErrorMiddleware()); // After all routes

Payment Authorization Not Parsed

Problem: Server cannot parse payment authorization.

Solutions:

  • Check header format is correct

  • Verify base64 encoding

  • Check JSON structure

  • Validate all required fields

// Debug: Log raw header
const authHeader = req.headers['x-payment-authorization'];
console.log('Raw header:', authHeader);

try {
  const authorization = PaymentAuthorization.fromHeader(authHeader);
} catch (error) {
  console.error('Parse error:', error);
}

Resource Encryption Fails

Problem: Resource encryption/decryption fails.

Solutions:

  • Verify RSA keys are correct format

  • Check keys are PEM format

  • Ensure public/private key pair matches

  • Verify encryption algorithm compatibility

// Test encryption
const { publicKey, privateKey } = generateKeyPair();
const encrypted = encryptResource('test', publicKey);
const decrypted = decryptResource(encrypted, privateKey);
console.log('Decrypted:', decrypted); // Should be 'test'

Configuration Issues

Configuration Not Initialized

Problem: Error that X402 is not initialized.

Solutions:

  • Call initX402() before using middleware

  • Ensure initialization happens once at startup

  • Check configuration values are set

// Initialize at startup
initX402({
  paymentAddress: process.env.PAYMENT_WALLET_ADDRESS!,
  tokenMint: process.env.TOKEN_MINT!,
  network: process.env.SOLANA_NETWORK!,
});

// Check if initialized
import { isInitialized } from '@shade402/express';
console.log('Initialized:', isInitialized());

Environment Variables Not Loaded

Problem: Configuration values are undefined.

Solutions:

  • Check .env file exists

  • Verify environment variables are loaded

  • Use dotenv package if needed

  • Check variable names match

// Load environment variables
import 'dotenv/config';

// Verify variables
console.log('Payment address:', process.env.PAYMENT_WALLET_ADDRESS);
console.log('Token mint:', process.env.TOKEN_MINT);

Network Issues

Wrong Network

Problem: Using wrong Solana network.

Solutions:

  • Check network configuration matches

  • Verify devnet vs mainnet

  • Ensure RPC endpoint matches network

  • Check token mint matches network

// Verify network
const network = process.env.SOLANA_NETWORK;
console.log('Network:', network);

// Devnet token mint
const devnetMint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

// Mainnet token mint (same for USDC)
const mainnetMint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

RPC Rate Limiting

Problem: RPC endpoint rate limits exceeded.

Solutions:

  • Use different RPC provider

  • Implement rate limiting

  • Add retry logic with backoff

  • Use premium RPC service

// Retry with exponential backoff
async function retryWithBackoff(fn: () => Promise<any>, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
    }
  }
}

TypeScript Issues

Type Errors

Problem: TypeScript compilation errors.

Solutions:

  • Install type definitions

  • Check TypeScript version

  • Verify import paths

  • Use correct type annotations

// Correct imports
import { X402Request } from '@shade402/express';
import { PaymentAuthorization } from '@shade402/core';

// Use types
app.get('/api/data',
  paymentRequired({ amount: '0.01' }),
  (req: X402Request, res) => {
    const payment: PaymentAuthorization | undefined = req.payment;
  }
);

Debugging Tips

Enable Verbose Logging

// Client-side
const client = new X402AutoClient(wallet, rpcUrl, {
  // Enable detailed logging in development
});

// Server-side
app.use((req, res, next) => {
  console.log('Request:', req.method, req.path);
  console.log('Headers:', req.headers);
  next();
});

Check Transaction Status

// Verify transaction on blockchain
const connection = new Connection(rpcUrl);
const signature = authorization.transactionHash;
const status = await connection.getSignatureStatus(signature);
console.log('Transaction status:', status);

Test Payment Flow Manually

// Step-by-step testing
const client = new X402Client(wallet);

// 1. Make request
const response = await client.get(url);
console.log('Status:', response.status);

// 2. Parse payment request
if (client.paymentRequired(response)) {
  const request = client.parsePaymentRequest(response);
  console.log('Payment request:', request);
  
  // 3. Create payment
  const authorization = await client.createPayment(request);
  console.log('Authorization:', authorization);
  
  // 4. Retry
  const retryResponse = await client.get(url, { payment: authorization });
  console.log('Retry status:', retryResponse.status);
}

Getting Help

If you're still experiencing issues:

  1. Check the Examples for working code

  2. Review Best Practices for common patterns

  3. Check Security for configuration issues

  4. Open an issue on GitHub with:

    • Error messages

    • Code snippets

    • Configuration (without secrets)

    • Network and environment details

Next Steps

Last updated