Troubleshooting Basics
“Something’s not working” → Get back to building in minutes, not hours
Every developer hits setup issues. The difference between shipping and struggling is knowing how to debug quickly. This guide solves 95% of common Saros SDK issues with copy-paste solutions.
🔍 Error Diagnosis Flow
Common Error Resolution Decision Tree
🚨 Emergency Quick Fixes
Can’t Connect to Solana
# Test connection
solana cluster-version
# If fails, try different RPC endpoint
solana config set --url https://api.devnet.solana.com
# Alternative endpoints:
# solana config set --url https://rpc.ankr.com/solana_devnet
# solana config set --url https://solana-api.projectserum.com
# Verify connection
solana cluster-version
No Devnet SOL
# Request devnet SOL (run multiple times)
solana airdrop 2
solana airdrop 2
solana airdrop 2
# Check balance
solana balance
# If airdrop fails, try:
# 1. Different RPC endpoint
# 2. Online faucet: https://solfaucet.com/
# 3. Ask in Saros Dev Station: https://t.me/saros_devstation
SDK Import Errors
# Clear npm cache
npm cache clean --force
# Reinstall dependencies
rm -rf node_modules package-lock.json
npm install
# For TypeScript issues
npm install -D typescript @types/node
# For Rust issues
cargo clean
cargo build
🔧 Common Development Issues
Issue 1: RPC Connection Failures
Symptoms : Timeouts, connection refused, network errors
// robust-connection.ts
import { Connection } from '@solana/web3.js' ;
const RPC_ENDPOINTS = [
'https://api.devnet.solana.com' ,
'https://rpc.ankr.com/solana_devnet' ,
'https://solana-api.projectserum.com' ,
];
async function createRobustConnection () : Promise < Connection > {
for ( const endpoint of RPC_ENDPOINTS ) {
try {
const connection = new Connection ( endpoint , 'confirmed' );
// Test connection
await connection . getVersion ();
console . log ( `✅ Connected via: ${ endpoint } ` );
return connection ;
} catch ( error ) {
console . log ( `❌ Failed: ${ endpoint } ` );
}
}
throw new Error ( 'All RPC endpoints failed' );
}
// Usage
const connection = await createRobustConnection ();
Issue 2: Transaction Failures
Symptoms : “Insufficient funds”, “Transaction simulation failed”
// transaction-validator.ts
import { Connection , PublicKey } from '@solana/web3.js' ;
async function validateTransaction (
connection : Connection ,
walletAddress : string ,
requiredSOL : number = 0.01
) {
try {
// 1. Check SOL balance for fees
const balance = await connection . getBalance ( new PublicKey ( walletAddress ));
const solBalance = balance / 1e9 ;
console . log ( `💰 SOL Balance: ${ solBalance . toFixed ( 4 ) } SOL` );
if ( solBalance < requiredSOL ) {
console . log ( `❌ Insufficient SOL for fees` );
console . log ( `🔧 Solution: solana airdrop 2` );
return false ;
}
// 2. Check network status
const health = await connection . getHealth ();
if ( health !== 'ok' ) {
console . log ( `⚠️ Network health: ${ health } ` );
return false ;
}
console . log ( '✅ Transaction validation passed' );
return true ;
} catch ( error ) {
console . error ( '❌ Validation failed:' , error );
return false ;
}
}
// Usage before any transaction
const isValid = await validateTransaction ( connection , 'YOUR_WALLET_ADDRESS' );
if ( ! isValid ) {
console . log ( '🛑 Fix issues before continuing' );
}
Issue 3: SDK Version Conflicts
Symptoms : Type errors, missing methods, compilation failures
# Check current versions
npm list @saros-finance/dlmm-sdk
npm list @solana/web3.js
# Update to latest compatible versions
npm install @saros-finance/dlmm-sdk@latest
npm install @solana/web3.js@^1.95.0
# For Rust
cargo update
cargo build
# If still failing, check version compatibility
npm info @saros-finance/dlmm-sdk
Issue 4: Wallet Integration Problems
Symptoms : Wallet not connecting, transaction signing failures
// wallet-debugger.ts
import { useWallet } from '@solana/wallet-adapter-react' ;
function WalletDebugger () {
const { wallet , connected , connecting , publicKey } = useWallet ();
console . log ( '🔍 Wallet Debug Info:' );
console . log ( `Connected: ${ connected } ` );
console . log ( `Connecting: ${ connecting } ` );
console . log ( `Wallet: ${ wallet ?. adapter . name || 'None' } ` );
console . log ( `Public Key: ${ publicKey ?. toString () || 'None' } ` );
if ( ! connected ) {
console . log ( '🔧 Troubleshooting:' );
console . log ( '1. Is wallet extension installed?' );
console . log ( '2. Is wallet unlocked?' );
console . log ( '3. Is correct network selected?' );
console . log ( '4. Try refreshing page' );
}
return (
< div >
< h3 > Wallet Status </ h3 >
< p > Connected : { connected ? '✅' : '❌' }</ p >
< p > Wallet : { wallet ?. adapter . name || 'None selected' }</ p >
< p > Address : { publicKey ?. toString () || 'Not connected' }</ p >
</ div >
);
}
🚨 Error Code Quick Reference
Saros SDK Errors
Error Code Meaning Quick Fix InsufficientBalanceNot enough tokens Check token balances SlippageExceededPrice moved too much Increase slippage tolerance PoolNotFoundInvalid pool address Verify pool address on explorer NetworkErrorRPC connection issue Try different RPC endpoint WalletNotConnectedWallet integration issue Check wallet connection state
Solana Errors
Error Meaning Solution Connection refusedRPC endpoint down Switch to backup endpoint Insufficient fundsNot enough SOL for fees solana airdrop 2Account not foundWrong network/address Check network config Transaction timeoutNetwork congestion Retry with higher priority
🔍 Debugging Checklist
When something doesn’t work, check in this order:
Network Connection
# Test basic connectivity
solana cluster-version
solana balance
# If failing:
solana config set --url https://api.devnet.solana.com
Dependencies
# Check versions
node --version # Should be 16+
npm list @saros-finance/dlmm-sdk
# Reinstall if needed
rm -rf node_modules && npm install
Wallet & Keys
# Verify wallet setup
solana address
solana balance
# Create new if needed
solana-keygen new --outfile ~/.config/solana/devnet-key.json
SDK Configuration
// Test SDK import
import * as saros from '@saros-finance/dlmm-sdk' ;
console . log ( '✅ SDK imported:' , Object . keys ( saros ));
🛡️ Environment Validation Script
Save this as validate-environment.ts for quick debugging:
import { Connection , PublicKey } from '@solana/web3.js' ;
async function validateEnvironment () {
console . log ( '🔍 Saros Development Environment Validation \n ' );
let allGood = true ;
// 1. Node.js version
const nodeVersion = process . version ;
console . log ( `Node.js: ${ nodeVersion } ` );
if ( parseInt ( nodeVersion . slice ( 1 )) < 16 ) {
console . log ( '❌ Node.js 16+ required' );
allGood = false ;
} else {
console . log ( '✅ Node.js version OK' );
}
// 2. Solana connection
try {
const connection = new Connection ( 'https://api.devnet.solana.com' );
const version = await connection . getVersion ();
console . log ( `✅ Solana connection: ${ version [ 'solana-core' ] } ` );
} catch ( error ) {
console . log ( '❌ Solana connection failed' );
allGood = false ;
}
// 3. SDK imports
try {
const dlmm = await import ( '@saros-finance/dlmm-sdk' );
console . log ( '✅ DLMM SDK import successful' );
} catch ( error ) {
console . log ( '❌ DLMM SDK import failed - run: npm install @saros-finance/dlmm-sdk' );
allGood = false ;
}
// 4. Wallet check (if configured)
try {
const { execSync } = require ( 'child_process' );
const address = execSync ( 'solana address' , { encoding: 'utf8' }). trim ();
console . log ( `✅ Wallet configured: ${ address . slice ( 0 , 8 ) } ...` );
} catch ( error ) {
console . log ( '⚠️ No wallet configured - OK for read-only operations' );
}
console . log ( ' \n ' + '=' . repeat ( 50 ));
if ( allGood ) {
console . log ( '🎉 Environment validation PASSED!' );
console . log ( '🚀 Ready to build with Saros SDKs!' );
} else {
console . log ( '❌ Environment validation FAILED' );
console . log ( '🔧 Fix issues above before continuing' );
}
return allGood ;
}
validateEnvironment ();
Run validation :
npx ts-node validate-environment.ts
🆘 Getting Help
Self-Help Resources
Run the validation script above - fixes 80% of issues
Check the specific SDK documentation for your chosen technology
Review error messages carefully - they often contain the solution
Test with minimal examples before building complex applications
Saros Dev Station Real-time developer support from Saros team and community
Quick answers to urgent issues
Share error messages and get immediate help
Connect with other developers facing similar challenges
Bug Reporting
If you found a bug in Saros SDKs:
Check if it’s reproducible with minimal example
Document the exact error and steps to reproduce
Report in Dev Station or GitHub issues
Consider the bug bounty program - get rewarded for finding issues!
Bug Bounty Rewards : High-impact bugs earn up to 2000 , e v e n m i n o r i s s u e s e a r n 2000, even minor issues earn 2000 , e v e nmin or i ss u ese a r n 1000. Your debugging might be profitable!
📊 Issue Resolution Statistics
Based on real developer support data:
95% of issues : Solved with RPC endpoint switching
3% of issues : SDK version mismatches
1% of issues : Actual bugs requiring code fixes
1% of issues : Complex environment-specific problems
Average resolution time : 5 minutes for common issues, 30 minutes for complex ones.
🎯 Prevention Tips
Always validate environment first . Run the validation script before starting any new project. 5 minutes of validation saves hours of debugging.
Use multiple RPC endpoints . Network issues are common in blockchain development. Always have fallback endpoints configured.
Test on devnet extensively . Every hour spent testing on devnet saves ten hours debugging on mainnet with real money.
Keep dependencies updated . Solana ecosystem moves fast. Weekly dependency updates prevent version conflict headaches.
🔬 Advanced Debugging Techniques
Transaction Simulation & Analysis
// Simulate before executing to catch errors early
async function debugTransaction ( transaction , connection ) {
try {
console . log ( '🔍 Simulating transaction...' );
const simulation = await connection . simulateTransaction ( transaction , {
commitment: 'processed' ,
sigVerify: false
});
if ( simulation . value . err ) {
console . log ( '❌ Simulation failed:' );
console . log ( 'Error:' , JSON . stringify ( simulation . value . err , null , 2 ));
console . log ( 'Logs:' , simulation . value . logs );
// Parse common error patterns
const logs = simulation . value . logs . join ( ' ' );
if ( logs . includes ( 'insufficient' )) {
console . log ( '💡 Likely cause: Insufficient balance or liquidity' );
} else if ( logs . includes ( 'slippage' )) {
console . log ( '💡 Likely cause: Slippage tolerance too low' );
} else if ( logs . includes ( 'account' )) {
console . log ( '💡 Likely cause: Missing or invalid accounts' );
}
return false ;
}
console . log ( '✅ Simulation successful' );
console . log ( 'Compute units:' , simulation . value . unitsConsumed );
console . log ( 'Fee estimate:' , ( simulation . value . unitsConsumed * 1000 ) / 1e9 , 'SOL' );
return true ;
} catch ( error ) {
console . error ( '❌ Simulation error:' , error );
return false ;
}
}
// Usage
const canExecute = await debugTransaction ( tx , connection );
if ( canExecute ) {
const signature = await connection . sendTransaction ( tx , [ wallet ]);
}
Real-time Error Monitoring
// Enhanced error tracking for production applications
class SarosErrorTracker {
constructor () {
this . errors = new Map ();
this . patterns = new Map ();
this . setupGlobalHandlers ();
}
setupGlobalHandlers () {
// Track unhandled promise rejections
process . on ( 'unhandledRejection' , ( error , promise ) => {
this . trackError ( 'unhandledRejection' , error , { promise });
});
// Track uncaught exceptions
process . on ( 'uncaughtException' , ( error ) => {
this . trackError ( 'uncaughtException' , error );
});
}
trackError ( category , error , context = {}) {
const errorKey = ` ${ category } _ ${ error . message } ` ;
const count = this . errors . get ( errorKey ) || 0 ;
this . errors . set ( errorKey , count + 1 );
// Track error patterns
if ( error . message . includes ( 'slippage' )) {
this . patterns . set ( 'slippage_errors' , ( this . patterns . get ( 'slippage_errors' ) || 0 ) + 1 );
} else if ( error . message . includes ( 'insufficient' )) {
this . patterns . set ( 'balance_errors' , ( this . patterns . get ( 'balance_errors' ) || 0 ) + 1 );
} else if ( error . message . includes ( 'network' )) {
this . patterns . set ( 'network_errors' , ( this . patterns . get ( 'network_errors' ) || 0 ) + 1 );
}
// Log recurring errors
if ( count > 2 ) {
console . warn ( `⚠️ Recurring error ( ${ count + 1 } times): ${ error . message } ` );
}
// Send to monitoring service in production
if ( process . env . NODE_ENV === 'production' ) {
this . sendToMonitoring ({
category ,
error: error . message ,
stack: error . stack ,
context ,
count: count + 1 ,
timestamp: new Date (). toISOString ()
});
}
}
getErrorStats () {
return {
totalErrors: Array . from ( this . errors . values ()). reduce (( sum , count ) => sum + count , 0 ),
uniqueErrors: this . errors . size ,
patterns: Object . fromEntries ( this . patterns ),
topErrors: Array . from ( this . errors . entries ())
. sort (( a , b ) => b [ 1 ] - a [ 1 ])
. slice ( 0 , 5 )
. map (([ error , count ]) => ({ error , count }))
};
}
async sendToMonitoring ( errorData ) {
// Integrate with your monitoring service
try {
await fetch ( '/api/errors' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( errorData )
});
} catch ( err ) {
console . warn ( 'Failed to send error to monitoring:' , err );
}
}
}
// Global instance
const errorTracker = new SarosErrorTracker ();
// Wrap Saros calls with error tracking
async function safeSwap ( params ) {
try {
return await dlmm . swap ( params );
} catch ( error ) {
errorTracker . trackError ( 'saros_swap' , error , { params });
throw error ;
}
}
Network Health Monitoring
// Monitor RPC endpoint health and performance
class RPCHealthMonitor {
constructor ( endpoints ) {
this . endpoints = endpoints ;
this . healthStats = new Map ();
this . currentEndpoint = 0 ;
this . startMonitoring ();
}
async startMonitoring () {
setInterval ( async () => {
await this . checkAllEndpoints ();
}, 30000 ); // Check every 30 seconds
}
async checkAllEndpoints () {
for ( const [ index , endpoint ] of this . endpoints . entries ()) {
const health = await this . checkEndpointHealth ( endpoint );
this . healthStats . set ( index , health );
}
// Auto-switch to best endpoint
const bestEndpoint = this . getBestEndpoint ();
if ( bestEndpoint !== this . currentEndpoint ) {
console . log ( `🔄 Switching from endpoint ${ this . currentEndpoint } to ${ bestEndpoint } ` );
this . currentEndpoint = bestEndpoint ;
}
}
async checkEndpointHealth ( endpoint ) {
const start = Date . now ();
try {
const connection = new Connection ( endpoint );
await connection . getSlot ();
const latency = Date . now () - start ;
return {
healthy: true ,
latency ,
lastCheck: Date . now (),
endpoint
};
} catch ( error ) {
return {
healthy: false ,
error: error . message ,
lastCheck: Date . now (),
endpoint
};
}
}
getBestEndpoint () {
const healthyEndpoints = Array . from ( this . healthStats . entries ())
. filter (([ _ , health ]) => health . healthy )
. sort (( a , b ) => a [ 1 ]. latency - b [ 1 ]. latency );
return healthyEndpoints . length > 0 ? healthyEndpoints [ 0 ][ 0 ] : 0 ;
}
getCurrentConnection () {
const endpoint = this . endpoints [ this . currentEndpoint ];
return new Connection ( endpoint , {
commitment: 'confirmed' ,
httpHeaders: {
'User-Agent' : 'Saros-Application/1.0'
}
});
}
getHealthReport () {
return Array . from ( this . healthStats . entries ()). map (([ index , health ]) => ({
endpoint: this . endpoints [ index ],
... health ,
isCurrent: index === this . currentEndpoint
}));
}
}
// Usage
const rpcMonitor = new RPCHealthMonitor ([
'https://api.devnet.solana.com' ,
'https://rpc.ankr.com/solana_devnet' ,
'https://devnet.genesysgo.net'
]);
// Use monitored connection
const connection = rpcMonitor . getCurrentConnection ();
Smart Retry Strategies
// Advanced retry logic with exponential backoff and circuit breaker
class SmartRetry {
constructor ( maxRetries = 3 , baseDelay = 1000 , maxDelay = 10000 ) {
this . maxRetries = maxRetries ;
this . baseDelay = baseDelay ;
this . maxDelay = maxDelay ;
this . failures = new Map ();
}
async execute ( operation , operationId = 'default' ) {
let lastError ;
for ( let attempt = 0 ; attempt < this . maxRetries ; attempt ++ ) {
try {
// Check circuit breaker
if ( this . isCircuitOpen ( operationId )) {
throw new Error ( `Circuit breaker open for ${ operationId } ` );
}
const result = await operation ();
// Reset failure count on success
this . failures . delete ( operationId );
return result ;
} catch ( error ) {
lastError = error ;
// Track failures
const failureCount = ( this . failures . get ( operationId ) || 0 ) + 1 ;
this . failures . set ( operationId , failureCount );
// Don't retry certain errors
if ( this . isNonRetryableError ( error )) {
console . log ( `❌ Non-retryable error: ${ error . message } ` );
break ;
}
// Calculate delay with jitter
const delay = Math . min (
this . baseDelay * Math . pow ( 2 , attempt ) + Math . random () * 1000 ,
this . maxDelay
);
console . log ( `⏳ Retry ${ attempt + 1 } / ${ this . maxRetries } after ${ delay } ms: ${ error . message } ` );
if ( attempt < this . maxRetries - 1 ) {
await new Promise ( resolve => setTimeout ( resolve , delay ));
}
}
}
throw lastError ;
}
isNonRetryableError ( error ) {
const message = error . message . toLowerCase ();
return message . includes ( 'invalid' ) ||
message . includes ( 'unauthorized' ) ||
message . includes ( 'forbidden' ) ||
message . includes ( 'malformed' );
}
isCircuitOpen ( operationId ) {
const failures = this . failures . get ( operationId ) || 0 ;
return failures > 5 ; // Open circuit after 5 consecutive failures
}
resetCircuit ( operationId ) {
this . failures . delete ( operationId );
console . log ( `🔄 Circuit breaker reset for ${ operationId } ` );
}
}
// Usage
const retry = new SmartRetry ( 3 , 1000 , 8000 );
const quote = await retry . execute ( async () => {
return await dlmm . getQuote ( params );
}, 'dlmm_quote' );
Environment Test Suite
#!/bin/bash
# save as test-environment.sh
echo "🧪 Saros Development Environment Test Suite"
echo "=========================================="
# Test 1: Node.js version
echo "1. Checking Node.js version..."
node_version = $( node --version | cut -d '.' -f1 | cut -d 'v' -f2 )
if [ " $node_version " -lt 16 ]; then
echo "❌ Node.js 16+ required (found: $( node --version ))"
exit 1
else
echo "✅ Node.js version OK: $( node --version )"
fi
# Test 2: Solana CLI
echo "2. Checking Solana CLI..."
if ! command -v solana & > /dev/null; then
echo "❌ Solana CLI not found"
echo "Install: sh -c \"\$ (curl -sSfL https://release.solana.com/v1.18.0/install) \" "
exit 1
else
echo "✅ Solana CLI found: $( solana --version )"
fi
# Test 3: Network connectivity
echo "3. Testing network connectivity..."
if solana cluster-version > /dev/null 2>&1 ; then
echo "✅ Connected to Solana network: $( solana config get | grep 'RPC URL' | awk '{print $3}')"
else
echo "❌ Cannot connect to Solana network"
echo "Try: solana config set --url https://api.devnet.solana.com"
exit 1
fi
# Test 4: Wallet setup
echo "4. Checking wallet setup..."
if solana balance > /dev/null 2>&1 ; then
balance = $( solana balance | awk '{print $1}' )
echo "✅ Wallet configured with $balance SOL"
if (( $( echo " $balance < 0.1" | bc - l ) )); then
echo "⚠️ Low SOL balance. Run: solana airdrop 2"
fi
else
echo "❌ No wallet configured"
echo "Create one: solana-keygen new --outfile ~/.config/solana/devnet-key.json"
exit 1
fi
# Test 5: NPM dependencies
echo "5. Checking NPM dependencies..."
if [ -f "package.json" ]; then
if npm list @saros-finance/dlmm-sdk > /dev/null 2>&1 ; then
echo "✅ Saros DLMM SDK installed"
else
echo "⚠️ Saros DLMM SDK not found. Run: npm install @saros-finance/dlmm-sdk"
fi
if npm list @solana/web3.js > /dev/null 2>&1 ; then
echo "✅ Solana Web3.js installed"
else
echo "⚠️ Solana Web3.js not found. Run: npm install @solana/web3.js"
fi
else
echo "⚠️ No package.json found - not a Node.js project"
fi
echo ""
echo "🎉 Environment test completed!"
echo "🚀 Ready for Saros development!"
Run the test suite:
chmod +x test-environment.sh
./test-environment.sh
📚 Comprehensive FAQ
Q: Why do my swaps work on devnet but fail on mainnet?
A: Common causes:
Different token addresses (devnet vs mainnet USDC)
Insufficient SOL for transaction fees (mainnet fees higher)
Pool exists on devnet but not mainnet
Different slippage requirements due to lower liquidity
Solution:
const NETWORK_CONFIG = {
devnet: {
USDC: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU' ,
defaultSlippage: 0.5
},
mainnet: {
USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' ,
defaultSlippage: 1.0 // Higher slippage for mainnet
}
};
const config = NETWORK_CONFIG [ process . env . NETWORK || 'devnet' ];
Q: How do I handle “Program failed to complete” errors?
A: This indicates insufficient compute units. Solutions:
import { ComputeBudgetProgram } from '@solana/web3.js' ;
// Add compute budget instructions
const computeUnitInstruction = ComputeBudgetProgram . setComputeUnitLimit ({
units: 400_000 , // Increase compute units
});
const priorityFeeInstruction = ComputeBudgetProgram . setComputeUnitPrice ({
microLamports: 2_000 , // Add priority fee for faster execution
});
transaction . add ( computeUnitInstruction );
transaction . add ( priorityFeeInstruction );
Q: My application becomes slow after running for a while. What’s wrong?
A: Likely memory leaks from unclosed connections or subscriptions:
// Proper cleanup
class SarosApp {
constructor () {
this . connections = [];
this . subscriptions = [];
}
cleanup () {
// Close all connections
this . connections . forEach ( conn => conn . close && conn . close ());
// Unsubscribe from all subscriptions
this . subscriptions . forEach ( sub => sub . unsubscribe && sub . unsubscribe ());
this . connections = [];
this . subscriptions = [];
}
}
// In React components
useEffect (() => {
return () => {
app . cleanup (); // Cleanup on unmount
};
}, []);
Q: How do I test my application without spending real tokens?
A: Use devnet exclusively for testing:
// Environment-based configuration
const getNetworkConfig = () => {
if ( process . env . NODE_ENV === 'development' ) {
return {
rpcUrl: 'https://api.devnet.solana.com' ,
tokens: DEVNET_TOKENS ,
cluster: 'devnet'
};
} else {
return {
rpcUrl: 'https://api.mainnet-beta.solana.com' ,
tokens: MAINNET_TOKENS ,
cluster: 'mainnet-beta'
};
}
};
// Never hardcode mainnet in development
const config = getNetworkConfig ();
🎯 Pro Tips for Advanced Users
Monitor RPC Performance : Use multiple RPC endpoints and automatically switch to the fastest one. Network latency significantly affects user experience.
Implement Circuit Breakers : Prevent cascading failures by implementing circuit breakers for external API calls and RPC requests.
Use Transaction Simulation : Always simulate transactions before execution in production. This catches 90% of errors before they reach users.
Log Everything in Development : Comprehensive logging during development makes production debugging much easier. Remove sensitive data before deploying.
Issues resolved? Return to your development journey: