Error Codes
This document provides a comprehensive reference for all error codes in the Hydra API.
gRPC Status Codes
Hydra uses standard gRPC status codes. All errors follow this format:
{
"code": 3,
"message": "invalid asset id",
"details": []
}
Common Status Codes
OK (0)
Description: Success - no error
When it occurs: Successful operation
Action: None required
CANCELLED (1)
Description: Operation was cancelled
When it occurs:
- Client cancelled request
- Stream was closed
Action: Retry if needed
UNKNOWN (2)
Description: Unknown error
When it occurs:
- Unexpected server error
- Unhandled exception
Action: Check request parameters, contact support if persists
INVALID_ARGUMENT (3)
Description: Client specified an invalid argument
Common causes:
- Invalid asset ID format
- Invalid network parameters
- Malformed request data
- Out-of-range values
Examples:
// Error: invalid asset id
{
"code": 3,
"message": "invalid asset id"
}
// Error: invalid network
{
"code": 3,
"message": "unsupported network protocol"
}
// Error: invalid amount
{
"code": 3,
"message": "amount must be positive"
}
Action:
- Verify asset ID format (e.g., "BTC" for Bitcoin, "0x..." for Ethereum)
- Check network protocol and chain_id
- Validate all numeric values
- Ensure required fields are present
DEADLINE_EXCEEDED (4)
Description: Operation timed out
When it occurs:
- Request took too long (>10 seconds for most operations)
- Network latency issues
Action:
- Retry with exponential backoff
- Check network connectivity
- For long operations, use streaming endpoints
NOT_FOUND (5)
Description: Requested resource not found
Common causes:
- Transaction doesn't exist
- Order not found
- Channel doesn't exist
- Payment not found
Examples:
// Error: transaction not found
{
"code": 5,
"message": "transaction not found: abc123..."
}
// Error: order not found
{
"code": 5,
"message": "order not found: order_xyz789"
}
Action:
- Verify resource ID is correct
- Check that resource exists on the specified network
- Ensure resource hasn't been deleted
ALREADY_EXISTS (6)
Description: Resource already exists
When it occurs:
- Attempting to create duplicate resource
- Market already initialized
- Channel already opened
Examples:
{
"code": 6,
"message": "market already initialized"
}
Action:
- Check if resource already exists
- Use update/modify operations instead of create
PERMISSION_DENIED (7)
Description: Caller doesn't have permission
When it occurs:
- Authentication failure
- Insufficient permissions
- Attempting to access another user's resource
Action:
- Verify authentication credentials
- Check API key permissions
- Ensure you own the resource
RESOURCE_EXHAUSTED (8)
Description: Resource has been exhausted
Common causes:
- Insufficient balance
- No liquidity available
- Rental capacity exceeded
- Channel capacity full
Examples:
// Error: insufficient balance
{
"code": 8,
"message": "insufficient onchain balance"
}
// Error: no liquidity
{
"code": 8,
"message": "no liquidity available in orderbook"
}
// Error: rental capacity
{
"code": 8,
"message": "rental amount exceeds available liquidity"
}
Action:
- Check balance before operations
- Add funds to wallet
- Try smaller amount
- Wait for liquidity to become available
FAILED_PRECONDITION (9)
Description: Operation rejected due to system state
Common causes:
- Channel not active yet
- Market not initialized
- Asset not supported
- Duration out of allowed range
Examples:
// Error: channel not ready
{
"code": 9,
"message": "channel not active for sending"
}
// Error: market not initialized
{
"code": 9,
"message": "market not initialized for this pair"
}
// Error: duration invalid
{
"code": 9,
"message": "rental duration below minimum"
}
Action:
- Wait for prerequisite conditions
- Initialize required resources first
- Check state before operations
- Verify parameter ranges
ABORTED (10)
Description: Operation was aborted
When it occurs:
- Concurrent modification conflict
- Transaction conflict
- Order already cancelled
Action: Retry operation
OUT_OF_RANGE (11)
Description: Operation outside valid range
Common causes:
- Amount too large or too small
- Fee rate invalid
- Duration out of range
Action:
- Check minimum/maximum values
- Adjust parameters to valid range
UNIMPLEMENTED (12)
Description: Operation not implemented
When it occurs:
- Feature not yet available
- Endpoint deprecated
- Network not supported
Action:
- Check API documentation for supported features
- Use alternative endpoint
INTERNAL (13)
Description: Internal server error
When it occurs:
- Database error
- Backend service failure
- Unexpected server condition
Action:
- Retry with exponential backoff
- Contact support if persists
UNAVAILABLE (14)
Description: Service temporarily unavailable
Common causes:
- Service maintenance
- Network issues
- Backend overload
Action:
- Retry with exponential backoff
- Check status page
- Wait and retry
DATA_LOSS (15)
Description: Unrecoverable data loss
When it occurs: Rare - serious server issue
Action: Contact support immediately
UNAUTHENTICATED (16)
Description: Request lacks valid authentication
When it occurs:
- Missing authentication
- Invalid credentials
- Expired session
Action:
- Provide authentication credentials
- Refresh authentication token
- Check API key is valid
Error Handling Best Practices
1. Implement Retry Logic
async function withRetry<T>(
operation: () => Promise<T>,
maxRetries: number = 3,
baseDelay: number = 1000
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await operation()
} catch (error) {
const code = error.code
// Don't retry client errors
if (code === 3 || code === 5 || code === 7) {
throw error
}
// Retry on server errors or timeouts
if (code === 13 || code === 14 || code === 4) {
const delay = baseDelay * Math.pow(2, i)
console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`)
await new Promise(resolve => setTimeout(resolve, delay))
continue
}
throw error
}
}
throw new Error('Max retries exceeded')
}
// Usage
const balance = await withRetry(() =>
walletClient.getBalance(request, {})
)
2. Graceful Error Handling
async function safeGetBalance(
client: WalletServiceClient,
network: Network,
assetId: string
): Promise<Balance | null> {
try {
const request = new GetBalanceRequest()
request.setNetwork(network)
request.setAssetId(assetId)
const response = await client.getBalance(request, {})
return response.getBalance()
} catch (error) {
switch (error.code) {
case 3:
console.error('Invalid asset ID:', assetId)
return null
case 5:
console.error('Asset not found:', assetId)
return null
case 14:
console.warn('Service unavailable, retrying...')
// Implement retry logic
return null
default:
console.error('Unexpected error:', error)
throw error
}
}
}
3. Check Preconditions
async function sendPaymentSafely(
walletClient: WalletServiceClient,
nodeClient: NodeServiceClient,
network: Network,
assetId: string,
amount: string
) {
// Check balance first
const balanceReq = new GetBalanceRequest()
balanceReq.setNetwork(network)
balanceReq.setAssetId(assetId)
const balanceResp = await walletClient.getBalance(balanceReq, {})
const available = balanceResp.getBalance()?.getOffchain()?.getLocal()
if (BigInt(available || '0') < BigInt(amount)) {
throw new Error('Insufficient balance')
}
// Proceed with payment
const paymentReq = new SendPaymentRequest()
// ... configure payment
return await nodeClient.sendPayment(paymentReq, {})
}
4. User-Friendly Messages
function getUserFriendlyError(error: any): string {
switch (error.code) {
case 3:
return 'Invalid input. Please check your entries.'
case 5:
return 'Resource not found. Please verify the ID.'
case 8:
if (error.message.includes('balance')) {
return 'Insufficient funds. Please add more to your wallet.'
}
if (error.message.includes('liquidity')) {
return 'Not enough liquidity available. Try a smaller amount.'
}
return 'Resource limit exceeded.'
case 9:
return 'Operation cannot be completed right now. Please try again later.'
case 14:
return 'Service temporarily unavailable. Please try again in a moment.'
default:
return 'An unexpected error occurred. Please try again.'
}
}
// Usage in UI
try {
await client.someOperation(request, {})
} catch (error) {
alert(getUserFriendlyError(error))
}
Service-Specific Errors
Wallet Service
| Error | Cause | Solution |
|---|---|---|
INVALID_ARGUMENT: invalid asset id | Wrong asset ID format | Check asset ID for network type |
NOT_FOUND: transaction not found | Transaction doesn't exist | Verify txid is correct |
Orderbook Service
| Error | Cause | Solution |
|---|---|---|
RESOURCE_EXHAUSTED: no liquidity | Empty orderbook | Wait or provide liquidity |
FAILED_PRECONDITION: market not initialized | Market doesn't exist | Call InitMarket first |
INVALID_ARGUMENT: amount below minimum | Amount too small | Increase to min_base_amount |
Swap Service
| Error | Cause | Solution |
|---|---|---|
RESOURCE_EXHAUSTED: insufficient balance | Not enough offchain funds | Use SimpleSwap instead |
FAILED_PRECONDITION: price exceeded tolerance | Price moved too much | Increase tolerance or retry |
Node Service
| Error | Cause | Solution |
|---|---|---|
FAILED_PRECONDITION: channel not active | Channel still opening | Use WaitForActiveAssetChannel |
NOT_FOUND: channel not found | Invalid channel_id | Verify channel exists |
RESOURCE_EXHAUSTED: insufficient capacity | Channel too small | Deposit more funds |
Rental Service
| Error | Cause | Solution |
|---|---|---|
RESOURCE_EXHAUSTED: rental capacity exceeded | Amount too large | Reduce rental amount |
FAILED_PRECONDITION: duration out of range | Invalid duration | Use allowed duration range |
Debugging Tips
- Enable verbose logging - Log all requests and responses
- Check error.message - Contains detailed error information
- Verify request format - Use protobuf debugging tools
- Test with small amounts - Use minimal values when debugging
- Check network status - Ensure blockchain is synced
- Monitor rate limits - Avoid excessive requests