> ## Documentation Index
> Fetch the complete documentation index at: https://developer.box.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Debugging your Box app

> A step-by-step playbook for diagnosing failed API calls, handling retries and timeouts, and using the App Diagnostics tool to troubleshoot your Box application.

export const SignupCTA = ({children}) => {
  return <div className="flex flex-wrap items-center gap-4 p-5 rounded-lg border border-gray-200 dark:border-gray-700 my-6" style={{
    background: "linear-gradient(135deg, rgba(0, 97, 213, 0.06), rgba(0, 97, 213, 0.02))"
  }}>
      <div className="flex-1 text-sm leading-relaxed text-gray-700 dark:text-gray-300" style={{
    minWidth: "280px"
  }}>
        {children}
      </div>
      <div className="flex flex-col items-center gap-2">
        <a href="https://account.box.com/signup/developer#ty9l3" className="signup-cta-button inline-flex items-center whitespace-nowrap px-5 py-2 text-sm font-semibold text-white no-underline">
          Get started for free
        </a>
        <a href="https://account.box.com/developers/console" className="signup-cta-login text-xs text-gray-500 dark:text-gray-400 no-underline whitespace-nowrap">
          Already have an account? Log in
        </a>
      </div>
    </div>;
};

export const RelatedLinks = ({title, items = []}) => {
  const getBadgeClass = badge => {
    if (!badge) return "badge-default";
    const badgeType = badge.toLowerCase().replace(/\s+/g, "-");
    return `badge-${badge === "ガイド" ? "guide" : badgeType}`;
  };
  if (!items || items.length === 0) {
    return null;
  }
  return <div className="my-8">
      {}
      <h3 className="text-sm font-bold uppercase tracking-wider mb-4">{title}</h3>

      {}
      <div className="flex flex-col gap-3">
        {items.map((item, index) => <a key={index} href={item.href} className="py-2 px-3 rounded related_link hover:bg-[#f2f2f2] dark:hover:bg-[#111827] flex items-center gap-3 group no-underline hover:no-underline border-b-0">
            {}
            <span className={`px-2 py-1 rounded-full text-xs font-semibold uppercase tracking-wide flex-shrink-0 ${getBadgeClass(item.badge)}`}>
              {item.badge}
            </span>

            {}
            <span className="text-base">{item.label}</span>
          </a>)}
      </div>
    </div>;
};

export const Link = ({href, children, className, ...props}) => {
  const localizedHref = href;
  return <a href={localizedHref} className={className} {...props}>
      {children}
    </a>;
};

When your Box application returns an unexpected error, fails intermittently, or stops processing requests, you need a structured workflow for finding the root cause. This guide walks you through one: how to read a Box error response, when and how to retry, how to set sensible timeouts, and which Box-provided tools to use at each step.

<SignupCTA>
  A free Box developer account gives you access to the Developer Console where you can reproduce issues with your own application and run the App Diagnostics Report.
</SignupCTA>

## Take a systematic approach

Most Box API failures come from one of a small number of causes: an invalid token, a missing scope, an item the app cannot access, a malformed request, or a transient server-side issue. Before you change code, break the failing flow into smaller, independently testable parts:

1. **Authentication.** Can your app obtain an access token? Is the token the right type for your auth method (OAuth 2.0, JWT, or Client Credentials Grant)?
2. **Authorization.** Does the token have the scopes the endpoint requires? Does the [service account](/platform/user-types#service-account) or user have access to the target item?
3. **Request construction.** Is the URL, HTTP method, header set, and body exactly what the API reference specifies?
4. **Server response.** What HTTP status code and Box error code came back? Was the request retried correctly if it was transient?
5. **Downstream side effects.** If you call other systems from a webhook or worker, did they succeed?

Test each step in isolation with a tool such as `curl` or Postman before you dig into application code.

## Inspect the API response

Box returns a structured error object for most `4xx` and `5xx` responses. Always log the full response body and the response headers — they are the single most useful piece of evidence you can collect.

```json theme={null}
{
  "type": "error",
  "status": 403,
  "code": "access_denied_insufficient_permissions",
  "help_url": "https://developer.box.com/guides/api-calls/permissions-and-errors/common-errors/",
  "message": "Access denied - insufficient permission",
  "request_id": "abcdef123456"
}
```

Use the fields as follows:

| Field        | What to do with it                                                                                                                                    |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`     | The HTTP status code. Tells you the broad category (auth, permission, not found, rate limit, server error).                                           |
| `code`       | The Box-specific error code. Map this to a fix using the <Link href="/guides/api-calls/permissions-and-errors/common-errors">Errors reference</Link>. |
| `message`    | A human-readable description. Often contains the specific field or value that failed validation.                                                      |
| `help_url`   | A direct link to documentation for the error.                                                                                                         |
| `request_id` | A unique identifier for the failed request. Include this in any support ticket.                                                                       |

<Note>
  Most Box API responses also include a `box-request-id` response header. This is a different value from the `request_id` field in the error body. Capture both when you can.
</Note>

For the full catalog of Box error codes by HTTP status, see <Link href="/guides/api-calls/permissions-and-errors/common-errors">Errors</Link>.

## Handle retries and timeouts

Not every failure is permanent. The right response to a transient error is to retry; the right response to a permanent error is to stop and surface it to the caller. Retrying a permanent error wastes quota and can amplify outages.

### Which responses to retry

| Status code                 | Retry? | Notes                                                                                                                                                 |
| --------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `408 Request Timeout`       | Yes    | The request did not reach the server in time. Retry with the same payload.                                                                            |
| `429 Too Many Requests`     | Yes    | You have been rate limited. Honor the `retry-after` header. See <Link href="/guides/api-calls/permissions-and-errors/rate-limits">Rate limits</Link>. |
| `500 Internal Server Error` | Yes    | Transient. Use exponential back-off.                                                                                                                  |
| `502 Bad Gateway`           | Yes    | Transient. Use exponential back-off.                                                                                                                  |
| `503 Service Unavailable`   | Yes    | Honor the `retry-after` header when present. Check the [Box status page](https://status.box.com/) if it persists.                                     |
| `4xx` (other)               | No     | These indicate a problem with the request itself. Fix the request before resending.                                                                   |

### Use exponential back-off with jitter

When you retry, increase the wait between attempts so you do not pile retries on top of a service that is already struggling. A simple pattern: wait `base * 2^attempt` seconds, capped at a maximum, plus a small random delay (jitter) to avoid thundering-herd retries from parallel workers.

```python theme={null}
import random, time

def backoff_seconds(attempt: int, base: float = 1.0, cap: float = 60.0) -> float:
    delay = min(cap, base * (2 ** attempt))
    return delay + random.uniform(0, delay * 0.1)
```

When the response includes a `retry-after` header, wait at least that many seconds before retrying instead of using your own back-off value.

```yaml theme={null}
retry-after: 100
```

### Set sensible request timeouts

Long-lived requests tie up workers and hide failures. Set an explicit timeout on every HTTP call your app makes to Box, and let the timeout fire a retry rather than waiting indefinitely. Choose values that match the endpoint: small JSON reads can use short timeouts, while uploads and AI extract calls need longer windows. If you use a [Box SDK](/guides/tooling/sdks), automatic retries and exponential back-off are already built in.

### Make retries safe

Retrying a `GET` is always safe. Retrying a `POST`, `PUT`, or `DELETE` can create duplicates if the original request actually succeeded but the response was lost. To make those retries safe:

* For chunked uploads, reuse the existing upload session and re-upload only the affected part. See <Link href="/guides/uploads/chunked">Chunked uploads</Link>.
* Treat a `409 item_name_in_use` on a retried create as "the original request already succeeded" rather than a real conflict, when that matches your flow. For example, if you retry `POST /files/content` and receive `item_name_in_use`, list the parent folder and look up the file you just tried to upload — in most cases the first attempt persisted before the response was lost.
* Before retrying a non-`GET` request, check whether the resource already exists. For example, before re-uploading a file, call `GET /folders/:id/items` on the destination folder and compare file names and sizes; before re-creating a collaboration, call `GET /folders/:id/collaborations`.

## Use the App Diagnostics tool

When you cannot reproduce a problem locally, or you need to see exactly what Box recorded for a request, run an <Link href="/guides/troubleshooting/app-diagnostics-report">App Diagnostics Report</Link> from the Developer Console.

The report exports a `.csv` of every API call your application made in a chosen 24-hour window. For each call it includes:

* The HTTP status code Box returned.
* The API request duration.
* The `API Request ID` — give this to Box Support and they can look up the exact request.
* The resource, sub-resource, HTTP method, and timestamp.

Use the App Diagnostics Report when you need to:

* Confirm whether a request ever reached Box.
* Find the request ID for a failed call that your own logs missed.
* Compare call volume against your expected pattern (for example, to see whether retries are running away).
* Provide Box Support with the precise call they need to investigate.

<Warning>
  The App Diagnostics Report does not include API calls made in the last 48 hours, or authorization and token API calls. For real-time investigations, rely on your application logs first.
</Warning>

For step-by-step setup instructions, see <Link href="/guides/troubleshooting/app-diagnostics-report">App Diagnostics Report</Link>.

## Capture the request ID for Box Support

If you need to escalate to [Box Support](https://support.box.com/hc/en-us/requests/new), include the full Box error response and at least one of:

* The `request_id` value from the error response body.
* The `box-request-id` response header from the failed call.
* The `API Request ID` column from an App Diagnostics Report.

With one of these IDs, Box Support can locate the exact request on the server side. Without one, investigating a single failure across millions of daily API calls is much slower.

## Debug common scenarios

The following checklist covers the failure modes most apps hit first.

### Authentication and token issues

| Symptom                                                                              | First check                                                                                                                                                          |
| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401 invalid_token`                                                                  | The token expired or was revoked. Refresh it, or request a new one. See <Link href="/guides/authentication/tokens/refresh">Refresh a token</Link>.                   |
| `400 invalid_grant` with "Current date time must be before the expiration date time" | The clock on the host running your app is out of sync with NTP. Re-sync time.                                                                                        |
| `400 invalid_client`                                                                 | The `client_id` or `client_secret` in your token request does not match the values in the Developer Console.                                                         |
| `400 unauthorized_client`                                                            | A JWT or CCG application has not been authorized by the enterprise admin. See <Link href="/guides/authorization/platform-app-approval">Platform App Approval</Link>. |

For UI-side authorization errors (admin console messages), see <Link href="/guides/authorization/common-errors">Authorization common errors</Link>.

### Permission and access issues

| Symptom                                               | First check                                                                                                                                                                                                                 |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `403 access_denied_insufficient_permissions`          | The user or [service account](/platform/user-types#service-account) does not have access to the item, or your app is missing the required scope. Confirm the item is shared with the service account if you use CCG or JWT. |
| `403 insufficient_scope`                              | The application scopes in the Developer Console do not include the one this endpoint needs. See <Link href="/guides/api-calls/permissions-and-errors/scopes">Scopes</Link>.                                                 |
| `404 not_found` on an item you can see in the web app | Your token belongs to a different user (often the [service account](/platform/user-types#service-account)) that has not been invited to the item.                                                                           |

### Rate limit and capacity issues

| Symptom                   | First check                                                                                                                                                              |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `429 rate_limit_exceeded` | Honor the `retry-after` header and back off. Review which limit you are hitting in <Link href="/guides/api-calls/permissions-and-errors/rate-limits">Rate limits</Link>. |
| Latency spikes plus 5xx   | Check the [Box status page](https://status.box.com/) for known incidents. Add exponential back-off if you have not already.                                              |

### Webhook issues

| Symptom                              | First check                                                                                                                                                                                           |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Webhooks never arrive                | Confirm the target URL is publicly reachable over HTTPS and returns `2xx` to a test `POST`. Check that the webhook is scoped to the correct trigger and item.                                         |
| Webhooks arrive but processing fails | Log the full payload, then replay it against your handler. Verify the signature before processing in production. See <Link href="/guides/webhooks/v2/signatures-v2">Verify webhook signatures</Link>. |

## Check the Box status page

If multiple unrelated calls start failing with `5xx` errors, before you dig into your own code, check [status.box.com](https://status.box.com/) for a known incident. When Box has an active incident, the right action is usually to back off and let the existing retry logic ride it out.

## Next steps

* Review the full catalog of error codes in <Link href="/guides/api-calls/permissions-and-errors/common-errors">Errors</Link>.
* Tune your retry policy against the limits in <Link href="/guides/api-calls/permissions-and-errors/rate-limits">Rate limits</Link>.
* Run an <Link href="/guides/troubleshooting/app-diagnostics-report">App Diagnostics Report</Link> the next time you see an unexpected failure.

<RelatedLinks
  title="RELATED GUIDES"
  items={[
{ label: translate("Errors"), href: "/guides/api-calls/permissions-and-errors/common-errors", badge: "GUIDE" },
{ label: translate("Rate limits"), href: "/guides/api-calls/permissions-and-errors/rate-limits", badge: "GUIDE" },
{ label: translate("App Diagnostics Report"), href: "/guides/troubleshooting/app-diagnostics-report", badge: "GUIDE" },
{ label: translate("Scopes"), href: "/guides/api-calls/permissions-and-errors/scopes", badge: "GUIDE" }
]}
/>
