# Error recovery

URL: https://briq.cloud/docs/api/errors

> Capacity and unavailable errors, request limits, safe retries and pending briq outcomes.

```json
{
  "error": {
    "code": "provider_error",
    "message": "the provider did not answer (create); retry in a moment",
    "details": { "op": "create", "status": 503 },
    "requestId": "req-example"
  }
}
```

Use the HTTP status and `error.code` together. The [error catalog](https://briq.cloud/docs/api/overview#errors) lists the known API mappings.
Keep `error.requestId` and the `x-request-id` header when reporting a failure.
Include the method, path, time and briq ID. Remove credentials, secret values and file contents.

## Capacity and unavailable infrastructure

A 503 `provider_error` can mean temporary capacity exhaustion, an unreachable service or a timeout.
It does not mean your plan or credential quota was exceeded. Capacity can remain unavailable across several attempts.
It also does not prove the operation made no changes: an answer can be lost after work starts.

For reads, retry after a delay with exponential backoff and jitter. Bound your attempts and total waiting time.
For writes, check the resource's current state first. Use the create replay rules below where supported.
Repeated failures need the request ID for investigation.

A 502 `provider_error` means the operation failed. Read the message and inspect current state before retrying.
Some billing failures also return 502. A 500 `internal` means an unexpected server failure; its generic message cannot identify the cause.
Other server HTTP errors can also use `internal`. Report persistent failures with their request IDs.

## Refusals that need action

| Status and code        | Next step                                                                                                |
| ---------------------- | -------------------------------------------------------------------------------------------------------- |
| 400 `validation`       | Fix the fields named in `message` or `details`. Select an available region when region validation fails. |
| 401 `unauthorized`     | Supply valid credentials or sign in again.                                                               |
| 403 `forbidden`        | Check credential permissions, team membership and the session's origin.                                  |
| 403 `plan_limit`       | Reduce the requested resources or change the team's plan.                                                |
| 402 `policy_violation` | Use a size, registry or sleep setting allowed by the credential's policy.                                |
| 402 `quota_exceeded`   | Release running work, raise the allowed limit or wait for the daily spend cap to reset.                  |
| 402 `payment_required` | Add credits or reduce the resources needed to start.                                                     |
| 404 `not_found`        | Check the route, resource ID, team and file path.                                                        |
| 409 `invalid_state`    | Read the message and current briq or exec state before repeating the operation.                          |
| 429 `quota_exceeded`   | Wait at least `retry-after` seconds. Reduce request frequency.                                           |

A busy machine can return 409 `invalid_state`; wait a few seconds and check its state again.
An exited process, explicit stop, duplicate name or closed command input needs a different action.
Execution-session limits also use 409: close a session or wait for a command to finish.
Machine-state errors can include `lastExit`, `machineState` and `providerSaid` in `details`.

## Size and protocol errors

A 413 `validation` means the request body, command or output is too large for one call.
Follow the response's limit. Reduce the payload or read smaller output chunks.
File validation can also return 400, including file-content limits; inspect `message` and `details.maxBytes` when present.
A missing readable file returns 404; a failed file write can return 502.

Shell and exec stream calls without a WebSocket upgrade return 426 `validation`.
Malformed upgrade handshakes return 400 `validation`. Protocol responses can omit `details` or `requestId`.
Use the endpoint's protocol and retain any response headers; do not assume every failure matches the JSON envelope.

## Retry creates with the same key

Use [Idempotency-Key](https://briq.cloud/docs/api/overview#retries) on supported create, fork and stack-up requests.
After a lost connection, repeat the same path and body with the same key.
A stored response has `Idempotent-Replayed: true`. Its body can contain the original request ID; keep the current header too.

* 409 `idempotency_in_progress`: wait briefly, then repeat with the same key and body.
* 422 `idempotency_mismatch`: restore the original path and body, or use a new key for an intentional new operation.
* A stored 5xx repeats that error. Check existing briqs and stacks before deciding to start another operation with a new key.
* A replay returns the original snapshot. Read the briq status for its current state.

These keys do not cover every write. Repeating an exec can run the command again.
For [command input](https://briq.cloud/docs/guides/run-a-long-command), `seq` makes a repeated input write safe.
A busy-input refusal asks for the same `seq`; a gap reports `lastSeq` so you can send the next number.

## Accepted work can still fail

```bash
curl https://api.briq.cloud/v1/briqs/bq_example \
  -H "Authorization: Bearer $BRIQ_API_KEY"
```

A create returns HTTP 201 with briq states. `wait: false` returns without waiting for readiness.
Even with waiting enabled, the wait can end while a briq is still `creating`.
Start returns HTTP 200 and can still show `starting` after its wait ends.
Acceptance means the operation was recorded; a pending state does not promise a machine was scheduled or became ready.

Poll `GET /v1/briqs/{id}` with a delay. Inspect `briq.state` and `briq.error`, even after a successful HTTP response.
With MCP, use `briq_status`. Read `briq_logs` when the process starts but fails or exits.
Do not create a replacement merely because the first call timed out.

| Outcome                                                         | What the status means                                                                                                                             |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `creating` or `starting`                                        | Work is pending. Temporary infrastructure failures can leave an `error` message while retries continue.                                           |
| `running`                                                       | The lifecycle operation reached running. Check application health and command results separately.                                                 |
| Create ends in `error` with `No capacity in <region> right now` | No machine was made and nothing is billed. Create again shortly, or in another region when the environment offers one. It is not retried for you. |
| Create ends in `error`                                          | Creation failed; inspect `error`. Cleanup attempts to stop any machine created; an unavailable service can delay cleanup.                         |
| Start returns to `stopped` with `error`                         | Starting failed. Inspect the reason before requesting another start.                                                                              |
| Stop returns to `running` with `error`                          | Stopping failed; the briq remains running and metered. Check before asking it to stop again.                                                      |
| `destroying` with `error`                                       | Destruction has not completed. Recovery continues; poll for `destroyed`.                                                                          |

Temporary unavailable errors receive bounded job retries. Pending creates can also resume during recovery.
There is no fixed completion-time guarantee. Stop client polling at your deadline and retain the briq ID for later checks.

An async exec's HTTP 202 is also an acceptance response. Check its exec status until completion.
A nonzero exit code or timeout is a command outcome, even when the status request returns HTTP 200.
For streamed commands, require a terminal result. A disconnected socket alone does not confirm completion or cancellation.
Stream terminal errors are separate from HTTP error envelopes:

| Terminal code                              | Meaning                                                                              |
| ------------------------------------------ | ------------------------------------------------------------------------------------ |
| `unsupported`, `exec_stream_refused`       | Streaming is unsupported or refused for the running guest.                           |
| `not_running`, `invalid`                   | The command runtime became unavailable or refused the stream.                        |
| `exec_cleanup_failed`, `exec_wait_failed`  | Cleanup or command completion could not be confirmed. Inspect state before retrying. |
| `internal`, `stream_failed`, `stream_lost` | The stream failed; command completion is uncertain.                                  |
| `cancel_unconfirmed`                       | Cancellation and remote cleanup could not be confirmed.                              |
| `session_ended`                            | A shell ended without a confirmed exit code.                                         |

See [Run a long command](https://briq.cloud/docs/guides/run-a-long-command) for exec states and input recovery.
