> ## 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: CONSENT_RECEIPT_INVALID (422)

> Resolve 422 CONSENT_RECEIPT_INVALID on the India DPDP Consent-Manager receipt endpoints — unknown or inactive manager, signature mismatch, tampered payload, key rotation, and how to re-issue receipts.

# Troubleshooting: CONSENT\_RECEIPT\_INVALID (422)

The India DPDP Phase II Consent Manager surface verifies the signed consent
receipts you persist or re-verify. When verification fails, the API rejects
the request with a **422** and code `CONSENT_RECEIPT_INVALID`:

```json theme={null}
{
  "error": {
    "code": "CONSENT_RECEIPT_INVALID",
    "status": 422,
    "details": {
      "consent_manager_id": "acme-cm-001"
    }
  }
}
```

This page maps each symptom to the check that fired and the fix you can run
yourself. For the concept behind receipts — registration, minting, and
canonicalized signing — see
[Consent Management → Consent receipts](/compliance/consent-management).

<Note>
  Consent receipts are a **tenant-owned** compliance control: your Consent
  Manager issues and signs the receipt, and Orbit verifies it against the
  public key you registered. The opt-in / opt-out record that results lives
  in your consent ledger — Orbit enforces nothing beyond the verification
  itself.
</Note>

***

## Symptom map

Work through the symptom table in order — the two endpoints both surface
exactly three failure shapes, and the message tells you which one fired.
`POST /api/v1/compliance/consent/receipts` mints a receipt;
`POST /api/v1/compliance/consent/receipts/:id/verify` re-checks a stored one.

| Symptom                                                                                          | Failing check                                                                                                          | Where it throws                                   |
| ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| "Unknown or inactive Consent Manager …"                                                          | The `consent_manager_id` on the mint request does not match a registered, active manager for this tenant               | Mint (`/receipts`) — before any cryptography runs |
| "Issuing Consent Manager is no longer registered for this tenant."                               | The manager reference stored on the receipt no longer resolves to a `consent_managers` row                             | Re-verify (`/receipts/:id/verify`)                |
| "Consent receipt signature verification failed… tampered, or the issuing manager rotated keys …" | ECDSA P-256 signature over the canonicalized payload does not verify against the manager's current SPKI PEM public key | Both endpoints — structure passed, crypto failed  |

The registry lists `CONSENT_RECEIPT_INVALID` as **varies** for HTTP status
because the mint endpoint rejects structurally-degenerate receipts at 422
`VALIDATION_ERROR` instead (a bad ISO-8601 timestamp, a malformed Base64URL
signature, an empty payload, or a payload that disagrees with the displayed
receipt fields). A **structural** problem gets the 422 `VALIDATION_ERROR`;
a **cryptographic** failure once structure passes gets the
`CONSENT_RECEIPT_INVALID` above. Only verified receipts are persisted —
verification always runs before storage.

***

## How receipts are issued, and when the API rejects the request

Two `CONSENT_RECEIPT_INVALID` paths exist:

1. **Mint** (`POST /compliance/consent/receipts`) — persist a receipt your
   Consent Manager signed. The manager must be registered and active;
   the signature must verify **before** anything is stored (Orbit never
   persists a receipt it cannot verify).
2. **Re-verify** (`POST /compliance/consent/receipts/:id/verify`) — re-check
   a stored receipt against the issuing manager's **current** key (an
   audit step, or a check on a suspected key rotation). The `{id}` accepts
   either the consent-record id or the `receipt_id`.

The "unknown manager" check and the signature check differ
between the two endpoints: at mint, a wrong `consent_manager_id` or a
known-but-inactive manager fires the wrong-manager throw. At re-verify,
a deleted manager row fires the no-longer-registered throw. In both
cases the signature failure means the same thing: the payload changed
after signing, or the key the platform holds is not the key that signed
(say the manager rotated keys without notifying you).

***

## Fix workflow: unknown or inactive Consent Manager

1. Register the manager under **Settings → Compliance → Consent managers**
   (or via `POST /api/v1/compliance/consent/managers`) with its machine
   `manager_id`, HTTPS URL, and SPKI PEM public key.
2. Point the mint request's `consent_manager_id` at that same `manager_id`
   value.
3. To fix manager deactivation, use `PUT /compliance/consent/managers/:id`
   with `is_active: true`.

On a pre-provisioned tenant (the `consent_managers` table missing) mint is
fail-closed with exactly this error — the read endpoints degrade to
empty / 404, but writes refuse. Re-run the provisioning migration before
minting receipts.

***

## Fix workflow: signature verification failed

Work through these in order — each isolates one of the three distict
causes:

1. **Key rotation.** The Consent Manager rotated its signing key without
   telling you. Register the manager's *new* public key under
   **Settings → Compliance → Consent managers** (or
   `PUT /compliance/consent/managers/:id` with the new `public_key`), and
   ask the manager to re-issue the receipt signed with the current key.
2. **Payload tampered in transit.** The JSON you posted disagrees with
   what was signed — a copy-paste edit, a middleware transform, or the
   manager changed the payload after signing. Paste the receipt envelope
   exactly as the manager produced it.
3. **Canonicalization mismatch.** Orbit canonicalizes the payload
   before hashing (sorted keys, insignificant-whitespace stripped — a
   minimal RFC 8785 JCS form, not a spec-complete implementation). If the
   manager signed a different serialization, ask it to sign the same
   sorted-key form Orbit uses.

Re-issue the receipt by posting the corrected envelope to
`POST /compliance/consent/receipts` again. The upsert targets the same
`contact_id` + `channel` pair, so a corrected re-issue replaces the failed
attempt's pending soft-fact with the verified one.

***

## Fix workflow: manager no longer registered

If `POST /receipts/:id/verify` says the issuing Consent Manager is no
longer registered, the receipt still exists but its trust anchor
(`consent_managers` row) was deleted. Re-register the manager with the
same `manager_id` — re-verification then re-checks against the new row's
key.

***

## Still failing? Pass to support

Include in the ticket:

* The `request_id` from `meta.request_id` on the 422 response
* Whether the failure was mint or re-verify, and the `consent_manager_id`
  from `error.details`
* The exact receipt envelope you posted (or the stored `{id}`), so support
  can replay the structure and signature checks without asking you to
  reproduce
