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

# Limits, statuses and errors

> Volume statuses, quotas on both halves of the service, pagination, and what to check when something misbehaves.

## Volume statuses

```mermaid theme={null}
stateDiagram-v2
    [*] --> creating: create
    creating --> available: provisioned
    creating --> error: provisioning failed
    available --> in_use: attached to an instance
    in_use --> available: detached
    available --> extending: extend
    extending --> available: resized
    extending --> error: resize failed
    available --> deleting: delete
    error --> deleting: delete
    deleting --> [*]: gone
```

| Status      | Meaning                                                      |
| ----------- | ------------------------------------------------------------ |
| `creating`  | Being provisioned. Not yet attachable.                       |
| `available` | Ready to attach, extend, snapshot or delete.                 |
| `in_use`    | Attached to an instance. Snapshot yes; extend and delete no. |
| `extending` | Resize in flight.                                            |
| `deleting`  | Teardown in progress.                                        |
| `error`     | The last operation failed. Read `error_message`.             |

Snapshots use a shorter set: `creating`, `available`, `deleting`, `error`.

## Quotas

Four storage counters, all scoped to your organization within a region:

| Quota               | Counts                                          |
| ------------------- | ----------------------------------------------- |
| `volumes`           | Volume count.                                   |
| `volume_storage_gb` | Sum of `size_gb` across your volumes.           |
| `snapshots`         | Snapshot count, scheduled and manual alike.     |
| `buckets`           | Bucket count — see [buckets](/storage/buckets). |

<Note>
  Quota is consumed for the lifetime of a row, not just while it is healthy. A
  volume parked in `error` still counts against `volumes` and
  `volume_storage_gb` — which mirrors what you can see — so delete failed
  volumes rather than leaving them.
</Note>

An extend reserves the delta before it starts, so an extend that would cross
`volume_storage_gb` is refused up front rather than half-applied.

## Listing and pagination

Volumes, snapshots and policies are listed newest-first and paginated with an
opaque cursor. Pass `marker` from the previous page's `meta` to get the next
one:

```bash theme={null}
GET /v1/volumes?limit=50&marker=<meta.marker>
```

<Warning>
  Do not infer the end of a list from a short page. Read `meta.has_more`, and
  keep passing `meta.marker` until it is false — a page can come back smaller
  than the `limit` you asked for.
</Warning>

Volume and snapshot listings also take `name` (case-insensitive substring) and
`status`; snapshots take `volume_id` to narrow to one volume, and policies take
`volume_id` and `enabled`.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Create rejected the volume type" icon="triangle-alert">
    Not every tier a volume can report is one you may create on. Use `ssd` or
    `nvme`. `GET /v1/volume-types` always lists exactly what is creatable.
  </Accordion>

  <Accordion title="Extend returns 409 VOLUME_NOT_AVAILABLE" icon="expand">
    The volume is not in `available`. Attached volumes (`in_use`) are the
    common case — detach, extend, re-attach. A volume mid-`creating`,
    `extending` or `deleting` also refuses, and settles on its own.

    A boot volume can never reach `available` while its instance exists, so an
    extend on one has no path to success. Move the data onto a separate volume,
    or rebuild the instance with a larger boot volume.
  </Accordion>

  <Accordion title="Delete returns 409 VOLUME_HAS_SNAPSHOTS" icon="camera">
    List them with `GET /v1/snapshots?volume_id=<id>` and delete them first. If
    a snapshot policy is still attached it may be creating new ones behind you
    — delete the policy, or pause it with `enabled: false`, before clearing the
    backlog.
  </Accordion>

  <Accordion title="A snapshot policy has stopped taking snapshots" icon="calendar-clock">
    Read `last_error` on the policy. The usual causes are an exhausted
    `snapshots` quota — clear space by lowering `retention_count` or deleting
    old snapshots — and a volume that was in a transient state when the window
    came around, which resolves itself on the next run.

    A policy with `enabled: false` produces nothing at all, and `next_run_at`
    tells you whether the schedule believes it is due.
  </Accordion>

  <Accordion title="A restored volume came back the wrong size" icon="hard-drive">
    A restore clones the snapshot and then grows to the `size_gb` you asked
    for, so it is never smaller than the snapshot's frozen size. The
    filesystem inside it is still the size it was when the snapshot was taken —
    expand it in the guest.
  </Accordion>

  <Accordion title="Status is error" icon="circle-alert">
    `error_message` carries the last failure. The row keeps its quota while it
    exists, so delete a volume or snapshot you do not intend to retry.
  </Accordion>
</AccordionGroup>

## Quotas

Two counters, both scoped to your organization within a region:

| Quota               | Counts               | Refused with    |
| ------------------- | -------------------- | --------------- |
| `buckets`           | Bucket count.        | `409` on create |
| `object_storage_gb` | Stored object bytes. | `403` on write  |

`object_storage_gb` is enforced by comparing what you actually store against the
limit, not by a running counter. That means space freed by a lifecycle
expiration, a version delete or a bucket purge comes back on its own — there is
no counter left holding a phantom charge against your cap.

## Troubleshooting

<AccordionGroup>
  <Accordion title="SignatureDoesNotMatch" icon="key-round">
    The secret does not match the access key, or something the client signed
    was rewritten in transit. Check first that the credential is right, then
    that your client is signing with SigV4 (`signature_version="s3v4"`) — the
    endpoint accepts nothing older.

    A key or query value containing a space or a `+` is a classic case: those
    have to be percent-encoded in the canonical request, and an SDK doing it
    correctly will interoperate.
  </Accordion>

  <Accordion title="RequestTimeTooSkewed" icon="clock">
    Your clock is more than 15 minutes from the server's. Fix time sync on the
    machine making the request; there is no way to widen the window.
  </Accordion>

  <Accordion title="AccessDenied on a bucket you own" icon="shield">
    An explicit `deny` in **either** layer wins, so start there: a bucket
    policy denying something is enough to block a caller their IAM policies
    allow, and the reverse holds too. With no explicit deny anywhere, you need
    an allow from one of the two — a bucket policy that names other principals
    is not itself a denial, but it will not stand in for the IAM grant you are
    missing.

    Deleting an object also fails with `403` when it is protected by an active
    retention period or a legal hold, which reads like a permission problem but
    is not one.
  </Accordion>

  <Accordion title="BucketNotEmpty on delete" icon="triangle-alert">
    Objects, versions, or in-flight multipart uploads remain. List uploads with
    `GET /v1/buckets/{bucket}/multipart-uploads` — an abandoned upload holds
    the bucket open just as an object does, and does not show in an object
    listing.
  </Accordion>

  <Accordion title="EntityTooSmall at completion" icon="layers">
    A part other than the last one is under 5 MiB. The floor is checked when
    the upload completes, so this surfaces after every part has been staged.
    Re-upload with larger parts.
  </Accordion>

  <Accordion title="The object is not encrypted despite the bucket default" icon="lock">
    A bucket default applies to writes made **after** it was set; existing
    objects are untouched. Re-upload anything already stored if you need it
    covered. Check `ServerSideEncryption` on a `HEAD` of the stored object,
    which is the only answer that reflects what was written.
  </Accordion>
</AccordionGroup>

## S3 error codes

The S3 endpoint answers in S3's own XML vocabulary, so an SDK's error handling
works unchanged:

| Code                                | Status | Meaning                                                                    |
| ----------------------------------- | ------ | -------------------------------------------------------------------------- |
| `AccessDenied`                      | 403    | Neither layer allowed the request.                                         |
| `SignatureDoesNotMatch`             | 403    | Signature did not verify.                                                  |
| `RequestTimeTooSkewed`              | 403    | More than 15 minutes of clock drift.                                       |
| `NoSuchBucket` / `NoSuchKey`        | 404    | Not found.                                                                 |
| `NoSuchUpload`                      | 404    | Unknown or already-aborted multipart upload.                               |
| `BucketAlreadyExists`               | 409    | Name taken by another account.                                             |
| `BucketNotEmpty`                    | 409    | Objects or uploads remain.                                                 |
| `InvalidBucketName`                 | 400    | Name broke one of the naming rules.                                        |
| `TooManyBuckets`                    | 400    | Your organization's bucket quota is exhausted.                             |
| `EntityTooLarge` / `EntityTooSmall` | 400    | Past the single-upload ceiling, or a short non-final part.                 |
| `InvalidPart` / `InvalidPartOrder`  | 400    | A named part is missing, its ETag mismatched, or the list is out of order. |
| `NotImplemented`                    | 501    | An S3 operation this endpoint does not route.                              |
