Error Codes & Messages
Jelli uses exactly the same error codes as Phantom but with enhanced error messages and additional debugging information to help developers build better dApps.
π― Error Code Reference
4001
User Rejected
User declined the request
User clicks "Cancel" or "Reject"
4100
Unauthorized
Wallet not connected or permission denied
Calling methods before connect()
-32000
Invalid Input
Missing or malformed parameters
Bad transaction data or missing fields
-32002
Resource Not Available
Wallet busy or network issues
Multiple simultaneous requests
-32003
Transaction Rejected
Invalid transaction format
Malformed transaction object
-32601
Method Not Found
Unsupported method called
Calling non-existent wallet methods
-32603
Internal Error
Something went wrong in Jelli
Unexpected wallet or network errors
π¦ Error Object Structure
Standard Phantom-Compatible Format
{
code: -32003, // Error code (same as Phantom)
message: "Jelli does not recognize a valid transaction.", // Jelli-branded message
name: "TransactionRejectedError" // Error type name
}
Enhanced Jelli Format
{
code: -32003, // Phantom-compatible code
message: "Jelli does not recognize a valid transaction.",
name: "TransactionRejectedError",
// Jelli enhancements:
category: "TRANSACTION", // Error category
timestamp: "2025-01-22T20:15:30.123Z", // When error occurred
metadata: { // Additional context
transactionType: "legacy",
transactionSize: 245,
networkLatency: 1200
}
}
π‘οΈ Handling Errors Properly
Basic Error Handling
try {
const { signature } = await provider.signAndSendTransaction(transaction);
console.log('β
Transaction successful:', signature);
} catch (error) {
console.error('β Transaction failed:', error.code, error.message);
// Handle specific errors
switch (error.code) {
case 4001:
showUserMessage("Transaction was cancelled");
break;
case 4100:
await provider.connect(); // Try reconnecting
break;
case -32003:
showUserMessage("Invalid transaction. Please try again.");
break;
default:
showUserMessage("Something went wrong. Please try again.");
}
}
Advanced Error Handling with Jelli Enhancements
try {
const result = await provider.signAndSendTransaction(transaction);
return result;
} catch (error) {
// Log enhanced error details for debugging
console.log('π Error Details:', {
code: error.code,
message: error.message,
category: error.category,
timestamp: error.timestamp,
metadata: error.metadata
});
// User-friendly error handling
switch (error.code) {
case 4001:
return { success: false, reason: 'user_cancelled' };
case 4100:
return { success: false, reason: 'not_connected' };
case -32000:
return {
success: false,
reason: 'invalid_input',
details: 'Please check your transaction parameters'
};
case -32002:
return {
success: false,
reason: 'wallet_busy',
details: 'Please wait and try again'
};
case -32003:
return {
success: false,
reason: 'invalid_transaction',
details: error.metadata?.transactionType ?
`Invalid ${error.metadata.transactionType} transaction` :
'Transaction format not recognized'
};
default:
return {
success: false,
reason: 'unknown_error',
details: error.message
};
}
}
π¨ Common Error Scenarios
1. User Rejection (4001)
// User clicks "Cancel" in Jelli popup
try {
await provider.signAndSendTransaction(transaction);
} catch (error) {
if (error.code === 4001) {
console.log("User cancelled the transaction");
// Don't retry automatically - respect user choice
}
}
2. Wallet Not Connected (4100)
// Calling methods before connect()
try {
await provider.signTransaction(transaction);
} catch (error) {
if (error.code === 4100) {
console.log("Wallet not connected, attempting to connect...");
await provider.connect();
// Now retry the operation
}
}
3. Invalid Transaction (-32003)
// Missing required fields or malformed transaction
try {
const invalidTx = new Transaction(); // Missing instructions!
await provider.signAndSendTransaction(invalidTx);
} catch (error) {
if (error.code === -32003) {
console.log("Transaction is invalid:", error.message);
// Check: instructions, recent blockhash, fee payer
}
}
4. Resource Not Available (-32002)
// Multiple simultaneous requests
try {
// Don't do this - multiple concurrent requests
Promise.all([
provider.signAndSendTransaction(tx1),
provider.signAndSendTransaction(tx2)
]);
} catch (error) {
if (error.code === -32002) {
console.log("Wallet is busy, waiting...");
// Implement retry with backoff
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
π§ Error Prevention Best Practices
1. Always Check Connection
async function safeTransaction(transaction) {
// Check connection first
if (!provider.isConnected) {
await provider.connect();
}
return provider.signAndSendTransaction(transaction);
}
2. Validate Transactions
function validateTransaction(transaction) {
if (!transaction.recentBlockhash) {
throw new Error("Missing recent blockhash");
}
if (!transaction.feePayer) {
throw new Error("Missing fee payer");
}
if (transaction.instructions.length === 0) {
throw new Error("No instructions in transaction");
}
}
3. Implement Retry Logic
async function transactionWithRetry(transaction, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await provider.signAndSendTransaction(transaction);
} catch (error) {
if (error.code === 4001) {
throw error; // Don't retry user rejection
}
if (i === maxRetries - 1) {
throw error; // Last attempt failed
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
π‘ Pro Tip: Jelli's enhanced error information helps you debug faster, but the core error codes remain identical to Phantom for seamless migration!
Last updated