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

# Diagnose failed app requests

> Distinguish State Machines gateway failures, native app errors, and incomplete request records.

`credentials.fetch()` returns an HTTP response for both successful and failed app calls. It does not convert a Salesforce error response into `StateMachinesError`, and it never retries a request.

Check the status and response body before assuming the request reached a native app operation. Network failures can reject without a response.

## Identify State Machines errors

The app URL can return a State Machines error before the app handles the request. These errors use a JSON `error` object.

| Code | Meaning and next step |
| - | - |
| `invalid_request` | The path or a header is not valid. Use the app URL from `connect()`. Do not send `StateMachines-*` headers other than `StateMachines-Environment-Token`. |
| `unauthenticated` | Obtain credentials for the exact app and confirm that the environment token reaches the app gateway. |
| `not_found` | Check the environment ID and app instance name in the URL. |
| `environment_not_running` | Read `error.status`. Resume a paused or failed environment when appropriate. A deleted environment needs a replacement. |
| `environment_starting` | Wait for startup before requesting again. |
| `environment_unavailable` | The app is restarting or did not answer. Inspect environment status and the `Retry-After` header. |
| `capacity_exceeded` | Reduce concurrent requests to the app. |
| `unsupported_protocol` | The app does not serve this path or API version, or the request body is compressed. Check the version's `apis` and remove `Content-Encoding`. |
| `body_too_large` | The request body is over 20 MiB. Split the operation using a supported native API. |
| `response_too_large` | The app response is over 4 MiB or compressed. Request a smaller page: lower `batchSize` in `Sforce-Query-Options` for SOQL, or set `maxRecords` for Bulk results. |
| `unavailable` | State Machines or the app could not serve the request. Wait for the `Retry-After` delay, then retry. |
| `internal_error` | Retry once, then report the `request-id` response header. |

An instruction to retry after a delay does not prove an ambiguous native write had no effect. Reconcile the app state before repeating a write.

## Inspect native app errors

Salesforce REST and Bulk errors use their native error arrays. SOAP failures use SOAP faults. OAuth failures use the OAuth error shape. Read the error code for that protocol, rather than parsing every body as a State Machines management error.

For field and object failures, inspect the target API version's describe response. For permission failures, verify the actor. For an unsupported operation, check [known differences](/apps/known-differences).

## Compare recorded requests

Use `sm.requests.list({ environmentId })` to inspect recorded calls, newest first. If a call is missing, confirm the environment and app name, clear status and method filters, and include the call's timestamp in the time range. Start a new first page after changing filters.

Check `respondedBy` on a matching record. `gateway` means the gateway produced the error response. The app may still have run the request. The gateway can fail after it forwards the request. Refusals from the app runner, such as `capacity_exceeded` and `unsupported_protocol`, are recorded with `respondedBy: 'app'` and a null `errorCode`.

`sm.requests.get(id)` adds selected headers and body previews. For a missing body, inspect `coverage`, `reason`, and `encoding` before downloading it. `omitted` means no body was stored. A body download then returns `not_found`. A binary body has no text preview. `previewTruncated` means only the start of a stored text body appears in the detail response.

`sm.requests.body(id, 'request')` or `'response'` returns the stored bytes, including any redactions. XML, multipart, and credential-route bodies can be omitted even when the request itself succeeded.

`sm.requests.stats({ environmentId, from, to })` summarizes recorded calls over a time range. Pass `from` and `to` as SDK `Date` values. Search requires both ends of the window too. The window can be at most 7 days. Recording is best effort, so missing entries or aggregate counts cannot establish that no request occurred.

Capture the environment ID, app version, method, path, response status, and sanitized error when reporting a problem. Exclude credentials and sensitive body data.

See [requests and audit events](/environments/observability) for filters, coverage fields, and statistics. For lifecycle changes rather than app responses, inspect the environment's audit events.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.