@bsv/sdk
Version:
BSV Blockchain Software Development Kit
598 lines (463 loc) • 15.6 kB
Markdown
# Error Reference
Complete reference for error codes, messages, and troubleshooting in the BSV TypeScript SDK.
## Error Categories
### Transaction Errors
#### INSUFFICIENT_FUNDS
**Code**: `INSUFFICIENT_FUNDS`
**Message**: "Insufficient funds to create transaction"
**Cause**: Wallet doesn't have enough UTXOs to cover transaction outputs and fees
**Solutions**:
- Check wallet balance with `listOutputs()`
- Reduce transaction amount
- Wait for pending transactions to confirm
- Use smaller fee rates
#### INVALID_TRANSACTION
**Code**: `INVALID_TRANSACTION`
**Message**: "Transaction validation failed"
**Cause**: Transaction structure or signatures are invalid
**Solutions**:
- Verify all inputs are properly signed
- Check script templates are correct
- Ensure transaction format is valid
- Validate all output amounts are positive
#### TRANSACTION_TOO_LARGE
**Code**: `TRANSACTION_TOO_LARGE`
**Message**: "Transaction exceeds maximum size limit"
**Cause**: Transaction size exceeds network limits
**Solutions**:
- Reduce number of inputs/outputs
- Use more efficient script templates
- Split into multiple transactions
- Optimize data storage methods
#### INVALID_SCRIPT
**Code**: `INVALID_SCRIPT`
**Message**: "Script execution failed"
**Cause**: Locking or unlocking script contains errors
**Solutions**:
- Validate script syntax with `Script.fromASM()`
- Check opcode usage and limits
- Verify script template implementation
- Test script execution in isolation
### Wallet Errors
#### WALLET_NOT_CONNECTED
**Code**: `WALLET_NOT_CONNECTED`
**Message**: "Wallet connection not established"
**Cause**: WalletClient not connected to substrate
**Solutions**:
- Call `await wallet.connectToSubstrate()`
- Check wallet application is running
- Verify network connectivity
- Restart wallet application if needed
#### AUTHENTICATION_FAILED
**Code**: `AUTHENTICATION_FAILED`
**Message**: "Wallet authentication failed"
**Cause**: User denied access or authentication expired
**Solutions**:
- Re-authenticate with wallet
- Check originator domain permissions
- Verify wallet trust settings
- Clear cached authentication state
#### WALLET_LOCKED
**Code**: `WALLET_LOCKED`
**Message**: "Wallet is locked or requires password"
**Cause**: Wallet requires user authentication
**Solutions**:
- Unlock wallet application
- Enter wallet password
- Check wallet auto-lock settings
- Verify user session is active
#### ACTION_REJECTED
**Code**: `ACTION_REJECTED`
**Message**: "User rejected the transaction"
**Cause**: User declined transaction in wallet UI
**Solutions**:
- Retry transaction with user consent
- Adjust transaction parameters
- Provide clearer transaction description
- Check transaction amounts and fees
### Network Errors
#### NETWORK_ERROR
**Code**: `NETWORK_ERROR`
**Message**: "Network request failed"
**Cause**: Connection issues with blockchain nodes
**Solutions**:
- Check internet connectivity
- Verify node endpoints are accessible
- Try alternative chain trackers
- Implement retry logic with exponential backoff
#### NODE_UNAVAILABLE
**Code**: `NODE_UNAVAILABLE`
**Message**: "Blockchain node is unavailable"
**Cause**: Target node is down or unreachable
**Solutions**:
- Switch to backup node endpoints
- Check node status and health
- Use multiple chain tracker instances
- Implement failover mechanisms
#### BROADCAST_FAILED
**Code**: `BROADCAST_FAILED`
**Message**: "Transaction broadcast failed"
**Cause**: Network rejected transaction or broadcast error
**Solutions**:
- Verify transaction is valid
- Check network fees are adequate
- Retry broadcast after delay
- Use alternative broadcast endpoints
#### TIMEOUT_ERROR
**Code**: `TIMEOUT_ERROR`
**Message**: "Request timeout exceeded"
**Cause**: Network request took too long
**Solutions**:
- Increase timeout values
- Check network latency
- Use faster endpoints
- Implement request cancellation
### Cryptographic Errors
#### INVALID_PRIVATE_KEY
**Code**: `INVALID_PRIVATE_KEY`
**Message**: "Private key is invalid or out of range"
**Cause**: Private key doesn't meet secp256k1 requirements
**Solutions**:
- Generate new key with `PrivateKey.fromRandom()`
- Validate key is within curve order
- Check key format and encoding
- Use proper key derivation methods
#### INVALID_PUBLIC_KEY
**Code**: `INVALID_PUBLIC_KEY`
**Message**: "Public key is invalid or not on curve"
**Cause**: Public key point is invalid
**Solutions**:
- Verify key derivation from private key
- Check point coordinates are valid
- Validate key format (compressed/uncompressed)
- Use `PublicKey.fromPrivateKey()` for generation
#### SIGNATURE_VERIFICATION_FAILED
**Code**: `SIGNATURE_VERIFICATION_FAILED`
**Message**: "Digital signature verification failed"
**Cause**: Signature doesn't match message and public key
**Solutions**:
- Verify message hash is correct
- Check signature format (DER encoding)
- Ensure correct public key is used
- Validate signature components (r, s values)
#### ENCRYPTION_FAILED
**Code**: `ENCRYPTION_FAILED`
**Message**: "Symmetric encryption operation failed"
**Cause**: AES encryption/decryption error
**Solutions**:
- Verify encryption key is valid
- Check data format and encoding
- Ensure proper IV/nonce usage
- Validate authentication tags
### SPV Verification Errors
#### INVALID_MERKLE_PROOF
**Code**: `INVALID_MERKLE_PROOF`
**Message**: "Merkle proof verification failed"
**Cause**: Merkle path doesn't lead to valid root
**Solutions**:
- Verify merkle path structure
- Check transaction hash calculation
- Validate block header merkle root
- Ensure proof completeness
#### BLOCK_HEADER_INVALID
**Code**: `BLOCK_HEADER_INVALID`
**Message**: "Block header validation failed"
**Cause**: Block header doesn't meet consensus rules
**Solutions**:
- Verify header hash and difficulty
- Check timestamp validity
- Validate previous block hash
- Ensure proper header format
#### CHAIN_VALIDATION_FAILED
**Code**: `CHAIN_VALIDATION_FAILED`
**Message**: "Blockchain validation failed"
**Cause**: Chain doesn't follow consensus rules
**Solutions**:
- Verify chain continuity
- Check difficulty adjustments
- Validate block timestamps
- Ensure proper chain selection
### Configuration Errors
#### INVALID_CONFIG
**Code**: `INVALID_CONFIG`
**Message**: "SDK configuration is invalid"
**Cause**: Configuration parameters are incorrect
**Solutions**:
- Validate configuration schema
- Check required parameters are present
- Verify network settings
- Use default configuration as baseline
#### UNSUPPORTED_NETWORK
**Code**: `UNSUPPORTED_NETWORK`
**Message**: "Network type is not supported"
**Cause**: Invalid network specification
**Solutions**:
- Use supported networks: mainnet, testnet, regtest
- Check network configuration
- Verify chain parameters
- Update SDK to latest version
## Error Interface
All SDK errors implement the `WalletErrorObject` interface:
```typescript
interface WalletErrorObject {
code: string
description: string
stack?: string
context?: Record<string, any>
}
```
## Error Handling Patterns
### Basic Error Handling
```typescript
try {
const result = await wallet.createAction({
description: 'Test transaction',
outputs: [{
satoshis: 100,
lockingScript: Script.fromASM('OP_DUP OP_HASH160 ... OP_EQUALVERIFY OP_CHECKSIG').toHex()
}]
})
} catch (error) {
if (error.code === 'INSUFFICIENT_FUNDS') {
console.log('Not enough funds available')
// Handle insufficient funds
} else if (error.code === 'WALLET_NOT_CONNECTED') {
console.log('Wallet connection required')
await wallet.connectToSubstrate()
} else {
console.error('Unexpected error:', error)
}
}
```
### Retry Logic with Exponential Backoff
```typescript
async function retryOperation<T>(
operation: () => Promise<T>,
maxRetries: number = 3,
baseDelay: number = 1000
): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await operation()
} catch (error) {
if (attempt === maxRetries) throw error
// Only retry on network errors
if (!['NETWORK_ERROR', 'TIMEOUT_ERROR', 'NODE_UNAVAILABLE'].includes(error.code)) {
throw error
}
const delay = baseDelay * Math.pow(2, attempt)
await new Promise(resolve => setTimeout(resolve, delay))
}
}
throw new Error('Max retries exceeded')
}
```
### Comprehensive Error Categorization
```typescript
function categorizeError(error: WalletErrorObject): 'user' | 'network' | 'system' | 'config' {
const userErrors = ['ACTION_REJECTED', 'AUTHENTICATION_FAILED', 'WALLET_LOCKED']
const networkErrors = ['NETWORK_ERROR', 'NODE_UNAVAILABLE', 'BROADCAST_FAILED', 'TIMEOUT_ERROR']
const systemErrors = ['INVALID_TRANSACTION', 'SIGNATURE_VERIFICATION_FAILED', 'ENCRYPTION_FAILED']
const configErrors = ['INVALID_CONFIG', 'UNSUPPORTED_NETWORK']
if (userErrors.includes(error.code)) return 'user'
if (networkErrors.includes(error.code)) return 'network'
if (systemErrors.includes(error.code)) return 'system'
if (configErrors.includes(error.code)) return 'config'
return 'system' // Default category
}
```
## Troubleshooting Guide
### Common Issues and Solutions
#### "RPC Error: no header should have returned false"
**Symptoms**: Error during `createAction` calls
**Cause**: Wallet input selection issues
**Solutions**:
1. Restart wallet application
2. Ensure wallet is fully synced
3. Use slightly larger amounts (200-500 satoshis)
4. Wait for wallet synchronization
5. Check for sufficient confirmed UTXOs
#### "Insufficient funds" with Available Balance
**Symptoms**: Error despite wallet showing balance
**Cause**: UTXOs not properly selected by wallet
**Solutions**:
1. Check UTXO status with `listOutputs()`
2. Verify UTXOs are confirmed
3. Restart wallet to refresh UTXO cache
4. Use manual input selection if supported
#### Transaction Broadcast Failures
**Symptoms**: Valid transactions rejected by network
**Cause**: Various network or validation issues
**Solutions**:
1. Verify transaction format and signatures
2. Check fee rates are adequate
3. Ensure inputs are unspent
4. Try alternative broadcast endpoints
#### Wallet Connection Issues
**Symptoms**: Cannot connect to wallet substrate
**Cause**: Wallet not running or permission issues
**Solutions**:
1. Ensure wallet application is running
2. Check originator domain permissions
3. Clear browser cache and cookies
4. Verify wallet trust settings
### Diagnostic Tools
#### Transaction Validation
```typescript
function validateTransaction(tx: Transaction): string[] {
const errors: string[] = []
if (tx.inputs.length === 0) {
errors.push('Transaction must have at least one input')
}
if (tx.outputs.length === 0) {
errors.push('Transaction must have at least one output')
}
const totalInput = tx.inputs.reduce((sum, input) => sum + input.satoshis, 0)
const totalOutput = tx.outputs.reduce((sum, output) => sum + output.satoshis, 0)
if (totalInput <= totalOutput) {
errors.push('Insufficient input value to cover outputs and fees')
}
return errors
}
```
#### Network Connectivity Test
```typescript
async function testNetworkConnectivity(chainTracker: ChainTracker): Promise<boolean> {
try {
const height = await chainTracker.getHeight()
return height > 0
} catch (error) {
console.error('Network connectivity test failed:', error)
return false
}
}
```
#### Wallet Health Check
```typescript
async function checkWalletHealth(wallet: WalletClient): Promise<{
connected: boolean
authenticated: boolean
balance: number
errors: string[]
}> {
const result = {
connected: false,
authenticated: false,
balance: 0,
errors: [] as string[]
}
try {
await wallet.connectToSubstrate()
result.connected = true
} catch (error) {
result.errors.push(`Connection failed: ${error.message}`)
}
try {
const outputs = await wallet.listOutputs({ limit: 1 })
result.authenticated = true
result.balance = outputs.totalValue || 0
} catch (error) {
result.errors.push(`Authentication failed: ${error.message}`)
}
return result
}
```
## Error Recovery Strategies
### Automatic Recovery
```typescript
class ErrorRecoveryManager {
private retryAttempts = new Map<string, number>()
private maxRetries = 3
async executeWithRecovery<T>(
operation: () => Promise<T>,
operationId: string
): Promise<T> {
try {
const result = await operation()
this.retryAttempts.delete(operationId)
return result
} catch (error) {
return this.handleError(error, operation, operationId)
}
}
private async handleError<T>(
error: WalletErrorObject,
operation: () => Promise<T>,
operationId: string
): Promise<T> {
const attempts = this.retryAttempts.get(operationId) || 0
if (attempts >= this.maxRetries) {
this.retryAttempts.delete(operationId)
throw error
}
// Implement recovery strategies based on error type
switch (error.code) {
case 'WALLET_NOT_CONNECTED':
await this.reconnectWallet()
break
case 'NETWORK_ERROR':
await this.switchToBackupNode()
break
case 'INSUFFICIENT_FUNDS':
await this.waitForConfirmations()
break
default:
throw error // No recovery strategy available
}
this.retryAttempts.set(operationId, attempts + 1)
return this.executeWithRecovery(operation, operationId)
}
private async reconnectWallet(): Promise<void> {
// Implement wallet reconnection logic
}
private async switchToBackupNode(): Promise<void> {
// Implement node failover logic
}
private async waitForConfirmations(): Promise<void> {
// Wait for pending transactions to confirm
await new Promise(resolve => setTimeout(resolve, 30000))
}
}
```
## Best Practices
### Error Logging
```typescript
class ErrorLogger {
static log(error: WalletErrorObject, context?: Record<string, any>): void {
const logEntry = {
timestamp: new Date().toISOString(),
code: error.code,
message: error.description,
context: { ...error.context, ...context },
stack: error.stack
}
// Log to appropriate destination based on severity
if (this.isCriticalError(error.code)) {
console.error('CRITICAL ERROR:', logEntry)
} else {
console.warn('ERROR:', logEntry)
}
}
private static isCriticalError(code: string): boolean {
return [
'INVALID_PRIVATE_KEY',
'SIGNATURE_VERIFICATION_FAILED',
'CHAIN_VALIDATION_FAILED'
].includes(code)
}
}
```
### User-Friendly Error Messages
```typescript
function getUserFriendlyMessage(error: WalletErrorObject): string {
const messages: Record<string, string> = {
'INSUFFICIENT_FUNDS': 'You don\'t have enough funds for this transaction.',
'ACTION_REJECTED': 'Transaction was cancelled.',
'WALLET_NOT_CONNECTED': 'Please connect your wallet to continue.',
'NETWORK_ERROR': 'Network connection issue. Please try again.',
'INVALID_TRANSACTION': 'Transaction format is invalid. Please check your inputs.'
}
return messages[error.code] || 'An unexpected error occurred. Please try again.'
}
```
This comprehensive error reference provides developers with the tools and knowledge needed to handle all types of errors that may occur when using the BSV TypeScript SDK.