Skip to content

Error Handling & Retry ​

Stock SDK includes built-in error handling and automatic retry mechanisms to help you handle unstable network conditions.

Default Behavior ​

SDK enables the following retry strategy by default:

OptionDefaultDescription
maxRetries3Maximum retry attempts
baseDelay1000msInitial backoff delay
maxDelay30000msMaximum backoff delay
backoffMultiplier2Backoff multiplier

Error Types That Trigger Retry ​

Error TypeRetry?
Request Timeout✅ Yes
Network Error (DNS/Connection)✅ Yes
HTTP 408 (Request Timeout)✅ Yes
HTTP 429 (Too Many Requests)✅ Yes
HTTP 500/502/503/504 (Server Errors)✅ Yes
HTTP 400/401/403/404 (Client Errors)❌ No

Exponential Backoff ​

When a request fails, SDK uses exponential backoff to calculate wait time:

delay = baseDelay × (backoffMultiplier ^ attempt)

Example (default config):

AttemptCalculationWait Time
1st1000 × 2⁰~1 second
2nd1000 × 2¹~2 seconds
3rd1000 × 2²~4 seconds

This strategy gives the server time to recover, avoiding continuous requests during overload.

Custom Retry Configuration ​

typescript
import { StockSDK } from 'stock-sdk';

const sdk = new StockSDK({
  timeout: 10000,
  retry: {
    maxRetries: 5,           // Max 5 retries
    baseDelay: 500,          // Initial delay 500ms
    maxDelay: 10000,         // Max delay 10 seconds
    backoffMultiplier: 1.5,  // Backoff multiplier 1.5
  }
});

Disable Retry ​

In some cases, you may want to disable automatic retry:

typescript
const sdk = new StockSDK({
  retry: {
    maxRetries: 0  // Disable retry
  }
});

Retry Callback ​

Use onRetry callback to monitor retry events for logging or debugging:

typescript
const sdk = new StockSDK({
  retry: {
    onRetry: (attempt, error, delay) => {
      console.log(`Retry attempt ${attempt}`);
      console.log(`Error: ${error.message}`);
      console.log(`Waiting ${Math.round(delay)}ms before retry...`);
    }
  }
});

Fine-grained Control ​

Retry Only on Specific Errors ​

typescript
const sdk = new StockSDK({
  retry: {
    retryOnTimeout: true,       // Retry on timeout
    retryOnNetworkError: false, // Don't retry on network error
    retryableStatusCodes: [503, 504], // Only retry on these status codes
  }
});

Provider-level Overrides ​

Legacy global timeout / retry / rateLimit / circuitBreaker settings still act as the default policy.
The new providerPolicies option only overrides those defaults for a specific provider, so existing initialization code remains compatible.

Typical Use Cases ​

  • Keep Tencent on the default rate
  • Lower the request rate only for eastmoney
  • Enable more aggressive retry or circuit breaker rules for a single provider
typescript
const sdk = new StockSDK({
  retry: {
    maxRetries: 2,
    baseDelay: 500,
  },
  rateLimit: {
    requestsPerSecond: 5,
    maxBurst: 10,
  },
  providerPolicies: {
    eastmoney: {
      timeout: 12000,
      retry: {
        maxRetries: 5,
        baseDelay: 800,
      },
      rateLimit: {
        requestsPerSecond: 3,
        maxBurst: 3,
      },
      circuitBreaker: {
        failureThreshold: 3,
        resetTimeout: 30000,
      },
    },
  },
});

Available Provider Names ​

  • tencent
  • eastmoney
  • sina
  • linkdiary
  • unknown

Host Fallback & Retry Budget ​

Some providers (e.g. eastmoney) ship with several mirror hosts. When the first host fails with a fallback-eligible error (network / timeout / 5xx, etc.), the SDK automatically switches to the next candidate host.

To avoid the maxRetries × hostCount latency blow-up, the SDK applies the following strategy:

  • First host: uses the full retry budget (default up to 4 attempts: 1 + maxRetries).
  • Subsequent fallback hosts: each is tried only once (maxRetries is forced to 0).

The total request count is therefore roughly (maxRetries + 1) + (candidateHosts - 1), which preserves disaster recovery while preventing long blocking. Unreachable hosts are also throttled by the circuit breaker and host health stats.

Error Handling ​

HttpError ​

When server returns a non-2xx status code, SDK throws HttpError:

typescript
import { StockSDK, HttpError } from 'stock-sdk';

const sdk = new StockSDK();

try {
  const quotes = await sdk.getSimpleQuotes(['invalid_code']);
} catch (error) {
  if (error instanceof HttpError) {
    console.log(`HTTP Error: ${error.status} ${error.statusText}`);
  } else {
    console.log(`Other Error: ${error.message}`);
  }
}

Timeout Error ​

Timeout errors appear as DOMException with name set to AbortError:

typescript
try {
  const quotes = await sdk.getSimpleQuotes(['sh000001']);
} catch (error) {
  if (error instanceof DOMException && error.name === 'AbortError') {
    console.log('Request timed out');
  }
}

Standardized Error Codes ​

If you want consistent error classification without losing the original TypeError / AbortError / HttpError instance, use getSdkErrorCode:

typescript
import { getSdkErrorCode, HttpError } from 'stock-sdk';

try {
  await sdk.getSimpleQuotes(['sh000001']);
} catch (error) {
  if (error instanceof HttpError) {
    console.log(`HTTP Error: ${error.status}`);
  }

  console.log(getSdkErrorCode(error));
  // Possible values: HTTP_ERROR / RATE_LIMITED / NETWORK_ERROR / TIMEOUT / CIRCUIT_OPEN ...
}

The onRetry callback still receives the original error instance with standardized metadata attached, so existing error handling stays compatible.

Configuration Reference ​

RetryOptions ​

PropertyTypeDefaultDescription
maxRetriesnumber3Maximum retry attempts
baseDelaynumber1000Initial backoff delay (ms)
maxDelaynumber30000Maximum backoff delay (ms)
backoffMultipliernumber2Backoff multiplier
retryableStatusCodesnumber[][408, 429, 500, 502, 503, 504]HTTP status codes to retry
retryOnNetworkErrorbooleantrueRetry on network errors
retryOnTimeoutbooleantrueRetry on timeout
onRetryfunction-Retry callback function

Released under the ISC License.