---
title: Error Codes
product: trilio-share-protection
doc_type: guide
version: master
source: git2docs (code-derived, validation-filtered)
canonical: https://git2docs.com/murali-balcha/docs/trilio-share-protection/trilio-share-protection-/error-codes
---

# Error Codes

_HTTP status codes returned by the service and their meanings_

## Overview

This page documents every HTTP status code that the `abaca-api` service can return and explains the structure of error responses. Understanding these codes helps you distinguish between failures you can fix yourself — such as a misconfigured bucket or a missing field — and failures that require your cloud operator to intervene. Every error carries a machine-readable `code` field and a `category` field that tell you precisely who must act and why, making it straightforward to handle errors programmatically or route them to the right team.

## Prerequisites

To make effective use of this reference you should already have:

- A working Keystone token or trust that allows you to call `abaca-api` endpoints (see [Authentication](../authentication))
- `python-abacaclient` installed if you are consuming the API through the Python SDK or the `openstack share protection` CLI
- Familiarity with standard HTTP semantics (2xx, 4xx, 5xx ranges)
- Access to your cloud's logging pipeline if you need to diagnose `operator_action_required` errors, because those failures are logged server-side with full tracebacks that are intentionally not surfaced to the caller

## Installation

> **Note for reviewer:** This page is a reference guide for HTTP error codes rather than an installable component; there are no installation steps specific to error-code handling. If you are setting up `abaca-api` for the first time, see the control-plane deployment guide. If you are installing `python-abacaclient` to consume these errors from Python, run:

```bash
pip install python-abacaclient
```

All error-handling behaviour described here is built into the service and the client library — no additional configuration is required to receive structured error responses.

## Configuration

Error response behaviour is built into `abaca-api` and is not configurable by tenants. The following aspects are fixed by the service:

| Aspect | Fixed value | Notes |
|---|---|---|
| Error envelope format | `{"code", "title", "detail", "category"}` | All four fields are always present |
| `category` values | `tenant_action_required` or `operator_action_required` | Tells you who must act |
| Internal detail exposure | Never | 500-class errors never include stack traces or internal state in the response body; those are written to the server log only |
| Content type | `application/json` | All error responses, including 404 and 405, use the canonical JSON envelope |

If you are using `python-abacaclient`, every non-2xx response is raised as an `AbacaClientError`. You can access the envelope fields as attributes:

```python
from abacaclient.exceptions import AbacaClientError

try:
    client.backups.create(...)
except AbacaClientError as exc:
    print(exc.status)    # integer HTTP status
    print(exc.code)      # e.g. "abaca.validation_error"
    print(exc.title)     # short human-readable summary
    print(exc.detail)    # instance-specific message
    print(exc.category)  # "tenant_action_required" or "operator_action_required"
```

## Usage

### Reading the error envelope

Every error response from `abaca-api` — regardless of status code — uses the same four-field JSON envelope:

```json
{
  "code": "abaca.target_preflight_failed",
  "title": "Backup Target Preflight Failed",
  "detail": "Bucket does not have object lock enabled.",
  "category": "tenant_action_required"
}
```

| Field | Type | Description |
|---|---|---|
| `code` | string | Stable, machine-readable identifier. Never localised. Use this in error-handling logic. |
| `title` | string | Short, human-readable summary of the error class. |
| `detail` | string | Instance-specific explanation of what went wrong for this particular request. |
| `category` | string | Either `tenant_action_required` or `operator_action_required`. See below. |

### Using `category` to route failures

The `category` field is the fastest way to decide what to do next:

- **`tenant_action_required`** — You can fix this without involving your cloud operator. Common causes include invalid request fields, a misconfigured S3 bucket, a revoked Keystone trust or Barbican secret, a quota limit, or a missing `force=true` flag on a destructive operation.
- **`operator_action_required`** — The infrastructure needs attention. No worker VMs are available, a backend service is down, or an internal consistency error occurred. File a support ticket and include the `code` value and the timestamp of the failed request so the operator can correlate it with server logs.

### HTTP status code summary

| Status | Meaning | Typical `category` |
|---|---|---|
| 200 | Request succeeded | — |
| 201 | Resource created successfully | — |
| 202 | Asynchronous action accepted | — |
| 204 | Resource deleted, no body | — |
| 400 | Bad request — invalid input or missing field | `tenant_action_required` |
| 401 | Authentication required — missing or invalid Keystone token | `tenant_action_required` |
| 403 | Forbidden — insufficient permissions, quota exceeded, or revoked trust | `tenant_action_required` |
| 404 | Resource not found | `tenant_action_required` |
| 405 | Method not allowed for this URL | `tenant_action_required` |
| 409 | Conflict — duplicate resource, dependents exist, or repository locked | varies (see table below) |
| 422 | Unprocessable entity — bucket failed preflight checks | `tenant_action_required` |
| 500 | Internal server error | `operator_action_required` |
| 503 | Service unavailable — no workers or backend unreachable | `operator_action_required` |

### Complete error code reference

The following table lists every stable error `code` value, the HTTP status it maps to, which category it carries, and what it means:

| `code` | HTTP | `category` | When you see it |
|---|---|---|---|
| `abaca.validation_error` | 400 | `tenant_action_required` | A request field is missing, has the wrong type, or fails a constraint. Check `detail` for the specific field. |
| `abaca.unauthorized` | 401 | `tenant_action_required` | No valid Keystone token was supplied, or the token has expired. |
| `abaca.forbidden` | 403 | `tenant_action_required` | Your token is valid but your role does not allow this operation. |
| `abaca.quota_exceeded` | 403 | `tenant_action_required` | You have reached the maximum number of targets, policies, or backups allowed for your project. |
| `abaca.trust_access_denied` | 403 | `tenant_action_required` | The Keystone trust or Barbican secret used by Abacá for this target has been revoked or is no longer accessible. Re-create the trust or rotate the secret and re-enroll the target. |
| `abaca.not_found` | 404 | `tenant_action_required` | The requested resource ID does not exist or does not belong to your project. |
| `abaca.method_not_allowed` | 405 | `tenant_action_required` | You used an HTTP method (e.g. `DELETE`) on a URL that does not support it. |
| `abaca.conflict` | 409 | `tenant_action_required` | A resource with conflicting identity already exists, or the requested state change is not valid for the current state. |
| `abaca.force_required` | 409 | `tenant_action_required` | You requested an in-place restore without setting `force=true`. Because in-place restore overwrites the share's contents, the API requires an explicit opt-in. |
| `abaca.target_has_dependents` | 409 | `tenant_action_required` | You tried to delete a backup target that still has protection policies or backups referencing it. Delete or reassign those resources first. |
| `abaca.repository_locked` | 409 | `operator_action_required` | Another job currently holds the single-writer lock on this Kopia repository. This resolves automatically when the running job finishes. If the lock is stuck, an operator can trigger reconciliation via `POST /admin/reconciliation/trigger`. |
| `abaca.target_preflight_failed` | 422 | `tenant_action_required` | Your S3 bucket did not pass the conformance preflight checks. Common causes: object lock is not enabled, the bucket uses path-style addressing when virtual-hosted is required, expiration lifecycle rules are present, or Abacá cannot reach the endpoint. Check `detail` for the specific check that failed. |
| `abaca.worker_unavailable` | 503 | `operator_action_required` | No worker VM with a free capacity slot is currently registered. Contact your operator to scale up the worker fleet. |
| `abaca.backend_unavailable` | 503 | `operator_action_required` | A required backend service (Manila, Barbican, or the message bus) could not be reached. This is a transient infrastructure issue. |
| `abaca.invalid_state_transition` | 500 | `operator_action_required` | A job was asked to move between two states with no legal edge in the state machine. This is an internal consistency error; contact your operator. |
| `abaca.kopia_error` | 500 | `operator_action_required` | The Kopia backup engine exited with a non-zero status during a job. Check operator logs for the Kopia stderr output. |
| `abaca.network_strategy_precondition` | 500 | `operator_action_required` | The network attachment strategy could not run because the share's Manila metadata is incomplete. This is a conductor-side bug; contact your operator. |
| `abaca.snapshot_strategy_precondition` | 500 | `operator_action_required` | The snapshot access strategy could not run because the selected strategy does not match this share's capabilities. Contact your operator. |
| `abaca.internal_error` | 500 | `operator_action_required` | An unexpected error occurred. Details are intentionally withheld from the response. Your operator can correlate the failure using server logs. |

## Examples

### Example 1 — Successful backup creation (202 Accepted)

A backup is accepted asynchronously. Poll the returned job to track progress.

```bash
curl -s -X POST https://abaca.example.com/backups \
  -H "X-Auth-Token: $OS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"share_id": "a1b2c3d4-...", "target_id": "e5f6a7b8-..."}'
```

**Expected response — HTTP 202:**
```json
{
  "id": "9c0d1e2f-...",
  "share_id": "a1b2c3d4-...",
  "target_id": "e5f6a7b8-...",
  "status": "queued",
  "crash_consistent": true,
  "kopia_snapshot_id": null
}
```

---

### Example 2 — Validation error (400)

Omitting a required field returns a 400 with `abaca.validation_error`.

```bash
curl -s -X POST https://abaca.example.com/backups \
  -H "X-Auth-Token: $OS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"share_id": "a1b2c3d4-..."}'
```

**Expected response — HTTP 400:**
```json
{
  "code": "abaca.validation_error",
  "title": "Invalid Request",
  "detail": "'target_id' is a required field.",
  "category": "tenant_action_required"
}
```

---

### Example 3 — Resource not found (404)

Referencing an ID that does not exist or does not belong to your project returns 404.

```bash
curl -s https://abaca.example.com/backups/does-not-exist \
  -H "X-Auth-Token: $OS_TOKEN"
```

**Expected response — HTTP 404:**
```json
{
  "code": "abaca.not_found",
  "title": "Resource Not Found",
  "detail": "The requested URL was not found.",
  "category": "tenant_action_required"
}
```

---

### Example 4 — Bucket preflight failure (422)

Registering a target whose bucket lacks object lock returns 422.

```bash
curl -s -X POST https://abaca.example.com/targets \
  -H "X-Auth-Token: $OS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "my-target", "endpoint": "https://s3.example.com", "bucket": "my-bucket", "barbican_secret_refs": ["https://barbican.example.com/v1/secrets/..."] }'
```

**Expected response — HTTP 422:**
```json
{
  "code": "abaca.target_preflight_failed",
  "title": "Backup Target Preflight Failed",
  "detail": "Bucket 'my-bucket' does not have S3 object lock enabled. Object lock must be configured at bucket creation time.",
  "category": "tenant_action_required"
}
```

**Fix:** Create a new bucket with object lock enabled at creation time (this cannot be added retroactively), then register that bucket as your target.

---

### Example 5 — In-place restore rejected without `force` (409)

Attempting to restore over the original share without the required opt-in:

```bash
curl -s -X POST https://abaca.example.com/restores \
  -H "X-Auth-Token: $OS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"backup_id": "9c0d1e2f-...", "mode": "in_place"}'
```

**Expected response — HTTP 409:**
```json
{
  "code": "abaca.force_required",
  "title": "Destructive Operation Requires force=true",
  "detail": "In-place restore will overwrite the share's contents. Set force=true to confirm.",
  "category": "tenant_action_required"
}
```

**Fix:** Repeat the request with `"force": true` in the body.

---

### Example 6 — No worker available (503)

```json
{
  "code": "abaca.worker_unavailable",
  "title": "No Worker Available",
  "detail": "No worker VM with a free slot is currently registered.",
  "category": "operator_action_required"
}
```

This is not something you can fix as a tenant. Contact your operator to scale the worker fleet or wait for a running job to complete and free a capacity slot.

---

### Example 7 — Handling errors in Python with `python-abacaclient`

```python
from abacaclient.exceptions import AbacaClientError

try:
    backup = client.backups.create(
        share_id="a1b2c3d4-...",
        target_id="e5f6a7b8-..."
    )
except AbacaClientError as exc:
    if exc.category == "tenant_action_required":
        # Something in your request or configuration needs fixing
        print(f"Fix required: [{exc.code}] {exc.detail}")
    elif exc.category == "operator_action_required":
        # Infrastructure issue — escalate
        print(f"Operator alert: [{exc.code}] {exc.title} (HTTP {exc.status})")
    else:
        raise
```

## Troubleshooting

Use the `code` and `category` fields in every error response as your first diagnostic signal — they tell you exactly what failed and who needs to act.

---

**Symptom:** Every request returns HTTP 401 with `abaca.unauthorized`.

**Likely cause:** Your Keystone token is missing, malformed, or has expired. Tokens have a finite lifetime set by your Keystone configuration.

**Fix:** Re-authenticate with Keystone to obtain a fresh token and set it in the `X-Auth-Token` header. If you are using `python-abacaclient` or the `openstack share protection` CLI, re-source your `openrc` file or refresh your `clouds.yaml` credentials.

---

**Symptom:** HTTP 403 with `abaca.trust_access_denied`.

**Likely cause:** The Keystone trust or Barbican secret that Abacá uses to act on your behalf for this backup target has been revoked, rotated, or expired since the target was enrolled.

**Fix:** Identify which target is affected (the `detail` field will name it), delete and re-enroll the target using valid Barbican secret references, and verify that the new trust is created successfully during enrollment.

---

**Symptom:** HTTP 422 with `abaca.target_preflight_failed`.

**Likely cause:** Your S3 bucket failed one or more of the conformance preflight checks. The most common causes are: object lock was not enabled at bucket creation time; expiration lifecycle rules are present on the bucket; the bucket is not reachable from Abacá's network; or the credentials stored in Barbican do not have read/write access.

**Fix:** Read the `detail` field to identify the specific failing check. If object lock is missing, you must create a new bucket — it cannot be added retroactively. Remove any expiration lifecycle rules. Supported S3-compatible backends are AWS S3, MinIO, Ceph RGW, ODF, and Wasabi.

---

**Symptom:** HTTP 409 with `abaca.target_has_dependents` when deleting a target.

**Likely cause:** One or more protection policies or backups still reference the target you are trying to delete. Abacá refuses to delete the target to avoid orphaning your backup data.

**Fix:** List and delete all policies attached to this target, then list and delete (or reassign) all backups stored in it. Once no policies or backups reference the target, the delete request will succeed.

---

**Symptom:** HTTP 409 with `abaca.force_required` during a restore.

**Likely cause:** You requested an in-place restore (`"mode": "in_place"`) without explicitly confirming the destructive operation.

**Fix:** Add `"force": true` to your restore request body. Be aware that in-place restore overwrites the current contents of the original share.

---

**Symptom:** HTTP 409 with `abaca.repository_locked`.

**Likely cause:** Another job is currently writing to the same Kopia repository and holds the single-writer lock. This is expected during normal concurrent operation.

**Fix:** Wait for the running job to finish — the lock is released automatically when the job transitions out of the `transferring` or `finalizing` state. If the lock appears stuck (no job is actively running), ask your operator to trigger reconciliation via `POST /admin/reconciliation/trigger`.

---

**Symptom:** HTTP 503 with `abaca.worker_unavailable`.

**Likely cause:** All registered worker VMs are fully occupied (running jobs equal their capacity slot count), or no workers are registered at all.

**Fix:** This is `operator_action_required`. Contact your operator to scale up the worker fleet or wait for a running job to finish and free a slot. You can check fleet status at `GET /admin/workers` if you have admin access.

---

**Symptom:** HTTP 503 with `abaca.backend_unavailable`.

**Likely cause:** A required backend service — Manila, Barbican, or the RabbitMQ message bus — is temporarily unreachable from the Abacá control plane.

**Fix:** This is `operator_action_required`. Retry the request after a short delay. If the error persists, contact your operator and provide the `code` value and the timestamp so they can correlate it with service logs.

---

**Symptom:** HTTP 500 with `abaca.internal_error` (or any other `operator_action_required` 500-class code).

**Likely cause:** An unexpected internal error occurred. The response body intentionally contains no internal details to avoid leaking sensitive information.

**Fix:** Record the exact timestamp and any resource IDs from the failed request. Contact your operator — the full traceback is written to the `abaca-api` server log and can be retrieved by correlating the timestamp. If you received `abaca.kopia_error`, the operator should also inspect the Kopia stderr output captured by the worker agent for that job.
