Error Handling
Handle Client and Server SDK envelopes, retries, and terminal errors safely.
Finatic SDKs return structured failures. Check the envelope for the SDK you use before reading data, and keep credentials and raw broker payloads out of user-visible errors.
Client SDK envelope
The browser Client SDK returns success, error, and warning:
1const result = await finatic.v1.listAccounts({ includeSyncStatus: true });
2
3if (result.error) {
4 console.error(result.error.code, result.error.message, result.error.status);
5 return;
6}
7
8const accounts = result.success?.data ?? [];
9for (const warning of result.warning ?? []) {
10 console.warn(warning.message);
11}
12Server SDK envelopes
The Node and Python Server SDKs return data, errors, warnings, and traceId:
1const result = await finatic.v1.listAccounts();
2
3if (result.errors?.length) {
4 console.error(result.traceId, result.errors);
5 return;
6}
7
8const accounts = result.data ?? [];
9for (const warning of result.warnings ?? []) {
10 console.warn(warning);
11}Keep traceId in tenant-safe internal logs and support reports. Never log API keys, Connect tokens, webhook secrets, or raw provider credentials.
Common first-run errors
| Code or status | Meaning | Action |
|---|---|---|
| Token 401 / expired | The one-time Connect token lived about 90 seconds | Mint a new token immediately before FinaticConnect.init |
SESSION_INVALID_STATE | Connect is incomplete or no active grant exists | Complete Connect and wait for account.grant.created |
ACCOUNT_ID_TYPE_MISMATCH | A tenant/company ID was used as accountId | Use the financial account ID from the grant event or listAccounts |
| 403 | The current grant or API key lacks access | Stop and repair authorization instead of retrying |
| 404 | The resource is absent or outside the authorized account | Verify identifiers and tenant ownership |
| 422 | Validation failed | Correct the request from returned field details |
| 429 | The rate limit was reached | Retry only a safe read after Retry-After |
Bounded retries for safe reads
Retry only idempotent reads after transport failures, 429, or transient 5xx responses. Bound attempts, honor Retry-After, add jitter, and surface the final error.
1const RETRYABLE_STATUS = new Set([429, 500, 502, 503, 504]);
2
3async function listAccountsWithRetry(maxAttempts = 3) {
4 for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
5 let result;
6
7 try {
8 result = await finatic.v1.listAccounts();
9 } catch (transportError) {
10 if (attempt === maxAttempts) throw transportError;
11 await new Promise((resolve) =>
12 setTimeout(resolve, 250 * 2 ** (attempt - 1)),
13 );
14 continue;
15 }
16
17 if (!result.error) return result.success?.data ?? [];
18
19 const status = result.error.status;
20 if (!status || !RETRYABLE_STATUS.has(status) || attempt === maxAttempts) {
21 throw new Error(result.error.message);
22 }
23
24 const retryAfterSeconds = Number(result.error.details?.retry_after ?? 0);
25 const backoffMs = Math.max(
26 retryAfterSeconds * 1000,
27 250 * 2 ** (attempt - 1),
28 );
29 await new Promise((resolve) =>
30 setTimeout(resolve, backoffMs + Math.floor(Math.random() * 100)),
31 );
32 }
33
34 throw new Error('Account read exhausted its retry budget');
35}
36Do not automatically retry order placement, modification, or cancellation with a new idempotency key. A timeout can happen after the broker accepted the command. Preserve the original key and reconcile order state before submitting another trade.
Readiness is asynchronous
account.grant.created confirms durable authorization. Initial account data may still be pending. Poll a bounded number of times or consume supported events, show a visible pending state, and finish with a timeout or error state instead of an infinite spinner.
Operational guidance
- Translate technical failures into safe user-facing messages.
- Log stable error codes, HTTP status, and
traceIdwith tenant-safe context. - Never retry 401, 403, 404, or 422 without changing the request or authorization state.
- Respect
Retry-Afterand use bounded exponential backoff for safe reads. - Preserve idempotency keys while reconciling trading commands.
- Alert on repeated terminal failures without exposing provider payloads or credentials.