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

# Troubleshooting: BYOK_KEY_UNAVAILABLE (409) and DECRYPTION_FAILED (502)

> Resolve 409 BYOK_KEY_UNAVAILABLE on a BYOK-enforced field-encryption call and the read-side 502 DECRYPTION_FAILED — revoked key, pending-only key, unprovisioned wrapped DEK, unreachable KMS, and stale ciphertext after rotate.

# Troubleshooting: BYOK\_KEY\_UNAVAILABLE (409) and DECRYPTION\_FAILED (502)

A BYOK-enforced tenant field-encryption call (encrypt or decrypt) fails
closed with a **409** and code `BYOK_KEY_UNAVAILABLE` when your
customer-managed key cannot serve the request. The read-side sibling is a
**502** with code `DECRYPTION_FAILED`, which signals a ciphertext problem
rather than a key-lifecycle problem:

```json theme={null}
{
  "error": {
    "code": "BYOK_KEY_UNAVAILABLE",
    "status": 409,
    "details": {
      "state": "revoked",
      "provider": "aws_kms",
      "fingerprint": "kf_9f2a…"
    }
  }
}
```

This page maps each cause to the check you can run yourself. For the
concept and lifecycle behind the error — register, activate, rotate,
revoke — see
[Customer-Managed Keys (BYOK)](/compliance/byok-customer-managed-keys), and
the dashboard walkthrough at
[Customer-Managed Keys guide](/guides/compliance-byok-keys).

<Note>
  BYOK is a **tenant-owned** control: you hold the key in your own KMS and
  Orbit stores only the reference. The refuse below is the platform
  honoring your recorded policy, not a platform fault — when it can be
  resolved from your side, this page tells you how.
</Note>

***

## Cause table

Read the current BYOK record with `GET /api/v1/compliance/byok` to tell
the causes apart — the `state` (`pending` / `active` / `revoked`),
`enforced` flag, and `fingerprint` decide which row applies.

| Cause                                                   | How to confirm                                                                                                                                                                           | Fix                                                                                                                                                                                                        |
| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Key revoked                                             | `state: "revoked"` on `GET /compliance/byok`. Revocation clears `enforce` and destroys the wrapped data-encryption key.                                                                  | A `revoked` state is terminal for that key — re-register a key afresh with `PUT /compliance/byok`, then activate with `enforce: true` again.                                                               |
| Key never activated                                     | `state: "pending"` while `enforced: true`. The `enforce` flag is recorded at activation; a pending key was never (or only partially) activated.                                          | Complete activation with `POST /compliance/byok/activate` and `enforce: true` — after you have granted Orbit's service identity decrypt access on your KMS side.                                           |
| Wrapped DEK not yet provisioned                         | `state: "active"` and `enforced: true`, but the wrapped data-encryption key was never written (activation raced, or an older activation predates provisioning).                          | Retry `POST /compliance/byok/activate` once; if it persists, open a ticket with the `request_id` from `meta.request_id`.                                                                                   |
| KMS unreachable                                         | The platform cannot resolve the key reference — the KMS endpoint is down, the service identity's decrypt grant was pulled, or the reference points at a deleted key/alias.               | Verify the KMS reachability and the decrypt grant on your side; confirm the registered reference still exists in your KMS. If the KMS is reachable and the grant is valid, escalate with the `request_id`. |
| Read-side cipher-key mismatch (502 `DECRYPTION_FAILED`) | A rotate left stale ciphertext behind: the stored `enc:v1` envelope was sealed under a previous key. This is **not** retry-safe — re-reading the same ciphertext returns the same error. | Do not retry. Open a ticket with the `request_id` so the stale ciphertext can be re-encrypted onto the current key.                                                                                        |

The lifecycle itself is documented on the
[BYOK concept page](/compliance/byok-customer-managed-keys#lifecycle-states):
`pending → active → revoked`, with rotate available from `pending` or
`active`. Revoke is refused on an already-revoked key
(`409 BYOK_ALREADY_REVOKED`), and re-enabling after revocation means
registering anew (`PUT`), not un-revoking.

***

## Decision checklist

Work through these in order before you change anything:

1. **Read the record.** `GET /api/v1/compliance/byok` and note `state` and
   `enforced`. Any authenticated user can read it; it never echoes the raw
   reference, only the truncated `fingerprint`.
2. **Match the state to a table row.** `revoked` → re-register; `pending`
   → activate; `active` with the error on a fresh deploy → provisioning
   race; `active` and stable → KMS reachability or the read-side mismatch.
3. **Confirm `enforce` flips on only with `active`.** Activation is the
   only path that can set `enforce: true` — re-check that it was run with
   `enforce: true` in the same call, not toggled later against a
   `pending` key.
4. **For `ENCRYPTION_FAILED` / `DECRYPTION_FAILED`, do not retry.** The
   write-side failure (IV or authTag generation failed) and the read-side
   502 are not retry-safe. Open a ticket with the `request_id` from
   `meta.request_id` on the response, exactly as the
   [FAQ entry for DECRYPTION\_FAILED](/reference/faq) instructs.

***

## What NOT to do

* **Do not disable `enforce` to bypass the refuse.** The refuse is your
  recorded policy doing its job; weakening it to get the call through
  leaves audit evidence that you ran outside your own policy, and a
  revoked key can never be re-enabled that way — re-register instead.
* **Do not rotate again while a rotate is in flight.** For an enforced
  key, rotate re-wraps the internal data-encryption key under the new
  reference; issuing another rotate before the first completes compounds
  the failure. Resolve the current rotation first — if it was refused
  with `409 BYOK_REWRAP_FAILED`, treat that as the blocker.
* **Do not re-paste the same ciphertext.** On a 502
  `DECRYPTION_FAILED`, the stored envelope pointed at a pre-rotate key.
  Re-reading it returns the same error every time.
* **Do not expect revocation to undo itself.** Revocation destroys the
  wrapped DEK and clears `enforce`; nothing short of a fresh `PUT`
  restores BYOK.

***

## When to escalate

Escalate to [support@devotel.io](mailto:support@devotel.io) when:

* The cause row is **KMS unreachable** and you have confirmed the KMS
  endpoint is up, the reference exists, and the decrypt grant on Orbit's
  service identity is intact — then the resolution failure is on the
  platform side.
* Any **502 DECRYPTION\_FAILED** — stale ciphertext needs re-encryption
  onto the current key, which only the platform can perform.
* **Provisioning did not self-heal** after one retry of
  `POST /compliance/byok/activate`.

Include in the ticket:

* The `request_id` from `meta.request_id` on the 409/502 response
* The `fingerprint` from `GET /compliance/byok` (never the raw reference)
* The lifecycle `state` and `enforced` values at failure time
* For KMS-reachability suspects: provider name and confirmation that the
  key/alias exists and the grant is active

***

## Related

* [Customer-Managed Keys (BYOK)](/compliance/byok-customer-managed-keys) —
  lifecycle, provider grammar, and the exact scope of `enforce`.
* [Customer-Managed Keys guide](/guides/compliance-byok-keys) — the
  dashboard walkthrough for the same lifecycle.
* [Error Codes reference](/reference/error-codes) — the
  `BYOK_KEY_UNAVAILABLE`, `ENCRYPTION_FAILED`, and `DECRYPTION_FAILED`
  rows and the other BYOK conflict codes (`BYOK_NOT_FOUND`,
  `BYOK_NOT_PENDING`, `BYOK_ALREADY_REVOKED`, `BYOK_REWRAP_FAILED`).
