Error Handling
Error types and error handling patterns in Node.js SDK
The SDK uses a hierarchical error system. All errors extend SSIError, which extends the standard Error.
Error Classes
| Error Class | Extends | Description |
|---|---|---|
SSIError | Error | Base error — has message, code, statusCode, responseBody (secrets redacted), headers |
APIError | SSIError | API returned an error. code is the server error code, the HTTP status is in statusCode. An HTTP 200 carrying a code other than 200/204 also throws APIError |
DuplicateRequestError | APIError | HTTP 409: clientRequestId or batchRequestId already used (see Batch Orders) |
AuthenticationError | SSIError | Authentication failed (wrong credentials, token expired). Does not extend APIError |
SmartOTPPendingError | AuthenticationError | Smart OTP not approved yet (HTTP 202, code 401114) |
SmartOTPRejectedError | AuthenticationError | Smart OTP was rejected |
ReauthenticationRequired | AuthenticationError | The session cannot be refreshed and no OTP was given: authenticate again with an OTP |
RateLimitError | SSIError | Rate limit exceeded — has retryAfterMs (milliseconds), limit, remaining, reset |
WebSocketError | SSIError | WebSocket connection or communication error |
TradingWSError | WebSocketError | The Trading WebSocket server returned an error frame — has status, errorCode, serverMessage |
ValidationError | SSIError | Input validation error |
ConfigurationError | SSIError | Configuration error (including an unknown option) |
Import
import {
SSIError,
APIError,
DuplicateRequestError,
AuthenticationError,
SmartOTPPendingError,
SmartOTPRejectedError,
ReauthenticationRequired,
RateLimitError,
WebSocketError,
TradingWSError,
ValidationError,
ConfigurationError,
} from '@ssi.developer/ssi-sdk';Basic Usage
try {
const token = await auth.authenticate('wrong_otp');
} catch (error) {
console.error(`Error: ${error.message}`);
}Detailed Error Handling
AuthenticationError is not an APIError, so the order of the instanceof branches no longer matters between those two classes. Subclasses (DuplicateRequestError, TradingWSError, SmartOTP*) must be checked before their parent if you want to handle them separately.
try {
const result = await trading.trading.placeLimitOrder(
'YOUR_ACCOUNT_NO', 'SSI', OrderSide.BUY, 100, 68000,
);
} catch (error) {
if (error instanceof ReauthenticationRequired) {
console.log('Need to re-authenticate with an OTP');
} else if (error instanceof AuthenticationError) {
console.log('Authentication failed');
} else if (error instanceof RateLimitError) {
console.log(`Rate limited, retry after ${error.retryAfterMs}ms`);
} else if (error instanceof DuplicateRequestError) {
console.log(`Duplicate id (HTTP 409): ${error.message}`);
} else if (error instanceof APIError) {
console.log(`API error ${error.statusCode} (code ${error.code}): ${error.message}`);
} else if (error instanceof ValidationError) {
console.log(`Validation: ${error.message}`);
} else if (error instanceof TradingWSError) {
console.log(`Trading WS: status=${error.status} code=${error.errorCode} msg=${error.serverMessage}`);
} else if (error instanceof WebSocketError) {
console.log(`WebSocket: ${error.message}`);
} else if (error instanceof ConfigurationError) {
console.log(`Config: ${error.message}`);
} else if (error instanceof SSIError) {
console.log(`SDK error: ${error.message}`);
} else {
console.log(`Unknown error: ${error}`);
}
}Error Properties
SSIError / APIError
| Property | Type | Description |
|---|---|---|
message | string | Error message |
code | string | number? | Error code (for APIError, the server's code) |
statusCode | number? | HTTP status code |
responseBody | unknown? | Raw response body (if available), secrets redacted |
headers | Record<string, string> | Response headers |
RateLimitError
| Property | Type | Description |
|---|---|---|
message | string | Error message |
retryAfterMs | number? | Time to wait before retry (milliseconds). Formerly named retryAfter (seconds) |
limit, remaining, reset | number? | Rate limit info sent by the server (if present) |
code defaults to 'RATE_LIMITED' and statusCode is 429. For GET requests the REST client waits by itself on a 429 (at most 3 retries, never waiting longer than 30 seconds).
TradingWSError
| Property | Type | Description |
|---|---|---|
status | number | Status code in the error frame (for example 429) |
errorCode | string | Server error code |
serverMessage | string | Server message |
Errors by feature
Batch Orders
For usage see API Services, section 5.6.
| Error | When | What to do |
|---|---|---|
ValidationError | Empty batch, over maxBatchOrders, or one bad order (missing field, clientRequestId too long, a cancel item without exactly one id...) | Fix the input. No request was sent |
DuplicateRequestError | HTTP 409: clientRequestId or batchRequestId already used today | Check the order book, do not resend under a different id |
AuthenticationError | Authentication failed (wrong credentials, token expired) | Authenticate again with an OTP |
RateLimitError | Request rate exceeded | Wait, then retry in a controlled way |
APIError | Other server errors (has statusCode, code), for example 400111 when batchRequestTime is outside the replay window | Read code and message, do not retry blindly |
A batch is never retried automatically.
Trading WebSocket
See API Services, section 7.4.
| Error | When |
|---|---|
TradingWSError | The server returned an error frame, or refused the connection after accepting the socket (HTTP 101). Has status, errorCode, serverMessage. Extends WebSocketError |
WebSocketError | Not connected, send failed, response timeout (not retried), socket closed before a response, or a missing private key for a state-changing command |
ValidationError | Bad input caught locally (for example subscribing several accounts, an empty or over-limit batch). Since the methods are async, the Promise is rejected |
A server status 429 becomes a TradingWSError with status 429. Rejected-signature codes 401006, 401008, 401013 are retried once by the SDK in signatureEncoding: 'auto' mode.
Error Handling Guidelines
- Use
instanceofto handle each error type. - Catch
AuthenticationErrorwhen you need to refresh tokens or get a new OTP.ReauthenticationRequiredmeans you must authenticate again with an OTP. - Catch
RateLimitErrorand respectretryAfterMsfor backoff. - Catch
APIErrorto handle business errors from the server. Codes401101-401104and401106-401108(refresh token unusable) force re-authentication. - Catch
WebSocketErrorwhen handling streaming connections. A failed firstconnect()throwsWebSocketErrororAuthenticationError. - Catch
ValidationErrorto check input before calling API. - Catch
ConfigurationErrorwhen configuration is missing or invalid. - Use
SSIErroras a fallback for all SDK errors.