The SDK ships with a built-in retry strategy (BoxRetryStrategy) that implements the RetryStrategy interface. The BoxNetworkClient, which serves as the default network client, uses this strategy to automatically retry failed API requests with exponential backoff.
The retry strategy exposes two methods:
shouldRetry — Determines whether a failed request should be retried based on the HTTP status code, response headers, attempt count, and authentication state.retryAfter — Computes the delay (in seconds) before the next retry attempt, using either the server-provided Retry-After header or an exponential backoff formula.| Parameter | Default | Description |
|---|---|---|
maxAttempts |
5 |
Maximum number of retry attempts for HTTP error responses (status 4xx/5xx). |
retryBaseInterval |
1 (second) |
Base interval used in the exponential backoff calculation. |
retryRandomizationFactor |
0.5 |
Jitter factor applied to the backoff delay. The actual delay is multiplied by a random value between 1 - factor and 1 + factor. |
maxRetriesOnException |
2 |
Maximum number of retries for network-level exceptions (connection failures, timeouts). These are tracked by a separate counter from HTTP error retries. |
The following diagram shows how BoxRetryStrategy.shouldRetry decides whether to retry a request:
shouldRetry(fetchOptions, fetchResponse, attemptNumber)
|
v
+-----------------------+
| status == 0 | Yes
| (network exception)? |----------> attemptNumber <= maxRetriesOnException?
+-----------------------+ | |
| No Yes No
v | |
+-----------------------+ [RETRY] [NO RETRY]
| attemptNumber >= |
| maxAttempts? |
+-----------------------+
| |
Yes No
| |
[NO RETRY] v
+-----------------------+
| status == 202 AND | Yes
| Retry-After header? |----------> [RETRY]
+-----------------------+
| No
v
+-----------------------+
| status >= 500 | Yes
| (server error)? |----------> [RETRY]
+-----------------------+
| No
v
+-----------------------+
| status == 429 | Yes
| (rate limited)? |----------> [RETRY]
+-----------------------+
| No
v
+-----------------------+
| status == 401 AND | Yes
| auth available? |----------> Refresh token, then [RETRY]
+-----------------------+
| No
v
[NO RETRY]
When the response does not include a Retry-After header, the retry delay is computed using exponential backoff with randomized jitter:
delay = 2^attemptNumber * retryBaseInterval * random(1 - factor, 1 + factor)
Where:
attemptNumber is the current attempt (1-based)retryBaseInterval defaults to 1 secondfactor is retryRandomizationFactor (default 0.5)random(min, max) returns a uniformly distributed value in [min, max]| Attempt | Base Delay | Min Delay (factor=0.5) | Max Delay (factor=0.5) |
|---|---|---|---|
| 1 | 2s | 1.0s | 3.0s |
| 2 | 4s | 2.0s | 6.0s |
| 3 | 8s | 4.0s | 12.0s |
| 4 | 16s | 8.0s | 24.0s |
When the server includes a Retry-After header in the response, the SDK uses the header value directly as the delay in seconds instead of computing an exponential backoff delay. This applies to any retryable response that includes the header, including:
202 Accepted with Retry-After (long-running operations)429 Too Many Requests with Retry-After5xx server errors with Retry-AfterThe header value is parsed as a floating-point number representing seconds.
Network-level failures (connection refused, DNS resolution errors, timeouts, TLS errors) are represented internally as responses with status 0. These exceptions are tracked by a separate counter (maxRetriesOnException, default 2) from the regular HTTP error retry counter (maxAttempts).
This means:
maxRetriesOnException times due to network exceptions, but each exception retry also increments the overall attempt counter, so the total number of retries across both exception and HTTP error types is bounded by maxAttempts.You can customize all retry parameters by initializing BoxRetryStrategy with the desired values and passing it to NetworkSession:
const auth = new BoxDeveloperTokenAuth({ token: 'DEVELOPER_TOKEN_GOES_HERE' });
const networkSession = new NetworkSession({
retryStrategy: new BoxRetryStrategy({
maxAttempts: 3,
retryBaseInterval: 2,
retryRandomizationFactor: 0.3,
maxRetriesOnException: 1,
}),
});
const client = new BoxClient({ auth, networkSession });
You can implement your own retry strategy by implementing the RetryStrategy interface and overriding the shouldRetry and retryAfter methods:
class CustomRetryStrategy implements RetryStrategy {
async shouldRetry(
fetchOptions: FetchOptions,
fetchResponse: FetchResponse,
attemptNumber: number,
): Promise<boolean> {
return fetchResponse.status >= 500 && attemptNumber < 3;
}
retryAfter(
fetchOptions: FetchOptions,
fetchResponse: FetchResponse,
attemptNumber: number,
): number {
return 1.0;
}
}
const auth = new BoxDeveloperTokenAuth({ token: 'DEVELOPER_TOKEN_GOES_HERE' });
const networkSession = new NetworkSession({
retryStrategy: new CustomRetryStrategy(),
});
const client = new BoxClient({ auth, networkSession });
You can configure request timeouts using timeoutConfig on NetworkSession.
The SDK supports the following timeout values, all in milliseconds:
| Parameter | Description |
|---|---|
responseHeadersTimeout |
Maximum time to wait for the response headers to arrive (covers DNS, TCP, TLS, and server processing). |
timeoutMs |
Maximum time to read the response body after headers are received. When responseHeadersTimeout is not set, applies as a single timeout for the entire request from start to finish. |
const auth = new BoxDeveloperTokenAuth({ token: 'DEVELOPER_TOKEN_GOES_HERE' });
const networkSession = new NetworkSession({
timeoutConfig: {
responseHeadersTimeout: 5000,
timeoutMs: 60000,
},
});
const client = new BoxClient({ auth, networkSession });
How timeout handling works:
responseHeadersTimeout: 60000 (60 seconds) and timeoutMs: 21600000 (6 hours).responseHeadersTimeout and timeoutMs are set, the SDK uses a phased timeout approach: responseHeadersTimeout is enforced first while waiting for the response headers. Once headers are received, the timer is reset to timeoutMs for reading the response body.timeoutMs is set (without responseHeadersTimeout), it applies as a single timeout for the entire request.Response headers timeout after <responseHeadersTimeout>ms. On request timeout, the error is Request timeout after <timeoutMs>ms. If retries are exhausted, the SDK throws BoxSdkError.