Error Handling
Handle errors gracefully in your Portal integration.
PortalSDKError and error codes
The SDK throws PortalSDKError with a code property so you can handle cases in code. Always check err instanceof PortalSDKError and switch on err.code:
import { PortalSDKError } from 'portal-sdk';
try {
await client.connect();
await client.authenticate(token);
} catch (err) {
if (err instanceof PortalSDKError) {
switch (err.code) {
case 'AUTH_FAILED':
// Invalid or expired token
break;
case 'CONNECTION_TIMEOUT':
case 'CONNECTION_CLOSED':
// Connection issues — is Portal running? Check serverUrl.
break;
case 'NOT_CONNECTED':
// Call connect() before other methods
break;
case 'UNEXPECTED_RESPONSE':
case 'SERVER_ERROR':
case 'PARSE_ERROR':
// Protocol or server error; err.message and optional err.details
break;
default:
break;
}
}
throw err;
}
Error codes
| Code | When |
|---|---|
NOT_CONNECTED | A method was called before connect() or after disconnect. |
CONNECTION_TIMEOUT | Connection did not open within connectTimeout. |
CONNECTION_CLOSED | Socket closed unexpectedly. |
AUTH_FAILED | Invalid or rejected auth token. |
UNEXPECTED_RESPONSE | Server sent an unexpected response type. |
SERVER_ERROR | Server returned an error (message in err.message). |
PARSE_ERROR | Failed to parse a message; optional err.details. |
Background / connection events
Listen for connection and background errors via on:
client.on({
onConnected: () => console.log('Connected'),
onDisconnected: () => console.log('Disconnected'),
onError: (e) => console.error('Portal error:', e),
});
Check the err parameter in each sendCommand callback; handle connection and auth failures before sending commands.
Common error patterns
Connection errors
try {
await client.connect();
} catch (error) {
if (error instanceof PortalSDKError && error.code === 'CONNECTION_TIMEOUT') {
console.error('Connection timeout - is Portal daemon running?');
} else if (error.message?.includes('ECONNREFUSED')) {
console.error('Connection refused - check serverUrl');
} else {
console.error('Connection error:', error);
}
}
Authentication errors
try {
await client.authenticate('token');
} catch (error) {
if (error instanceof PortalSDKError && error.code === 'AUTH_FAILED') {
console.error('Invalid auth token');
} else {
console.error('Auth error:', error);
}
}
Payment errors
client.requestSinglePayment(userPubkey, [], request, (status) => {
if (status.status === 'error') {
console.error('Payment error:', status.reason);
} else if (status.status === 'user_failed') {
console.error('Payment failed:', status.reason);
// Common reasons: insufficient funds, routing failure
}
});
Handle err != null in callbacks; retry connect(authToken) on failure.
Error Recovery
Connection Retry
async function connectWithRetry(maxAttempts = 3, delayMs = 1000) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
await client.connect();
console.log('Connected successfully');
return true;
} catch (error) {
console.log(`Connection attempt ${attempt} failed`);
if (attempt < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
}
console.error('Failed to connect after retries');
return false;
}
Automatic Reconnection
client.on({
onDisconnected: () => {
console.log('Disconnected, attempting reconnect...');
setTimeout(async () => {
try {
await client.connect();
await client.authenticate(process.env.AUTH_TOKEN);
console.log('Reconnected successfully');
} catch (error) {
console.error('Reconnection failed:', error);
}
}, 5000);
}
});
Check err in every sendCommand callback; implement retry for connect; log errors with context.
Best Practices
- Always use try-catch for async operations
- Check status codes in callbacks
- Implement retry logic for critical operations
- Log errors with context
- Show user-friendly messages to end users
Always check the callback err parameter; use environment or config for URLs and token.
Next: Authentication Guide